diff -Nru libgoogle-gson-java-2.4/CHANGELOG.md libgoogle-gson-java-2.8.2/CHANGELOG.md --- libgoogle-gson-java-2.4/CHANGELOG.md 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/CHANGELOG.md 2017-09-20 01:41:34.000000000 +0000 @@ -1,19 +1,378 @@ Change Log ========== -## Version 2.4.0 +## Version 2.8.2 +_2017-09-19_ [GitHub Diff](https://github.com/google/gson/compare/gson-parent-2.8.1...gson-parent-2.8.2) + * Introduced a new API, `JsonElement.deepCopy()` + * Numerous other bugfixes -_RELEASE DATE TBA_ +## Version 2.8.1 +_2017-05-30_ [GitHub Diff](https://github.com/google/gson/compare/gson-parent-2.8.0...gson-parent-2.8.1) + * New: `JsonObject.keySet()` + * `@JsonAdapter` annotation can now use `JsonSerializer` and `JsonDeserializer` as well. + +## Version 2.8 +_2016-10-26_ [GitHub Diff](https://github.com/google/gson/compare/gson-parent-2.7...gson-parent-2.8.0) + * New: `TypeToken.getParameterized()` and `TypeToken.getArray()` make it easier to + register or look up a `TypeAdapter`. + * New: `@JsonAdapter(nullSafe=true)` to specify that a custom type adapter handles null. + +## Version 2.7 +_2016-06-14_ [GitHub Diff](https://github.com/google/gson/compare/gson-parent-2.6.2...gson-parent-2.7) + * Added support for JsonSerializer/JsonDeserializer in @JsonAdapter annotation + * Exposing Gson properties excluder(), fieldNamingStrategy(), serializeNulls(), htmlSafe() + * Added JsonObject.size() method + * Added JsonWriter.value(Boolean value) method + * Using ArrayDeque, ConcurrentHashMap, and other JDK 1.6 features + * Better error reporting + * Plenty of other bug fixes + +## Version 2.6.2 +_2016-02-26_ [GitHub Diff](https://github.com/google/gson/compare/gson-parent-2.6.1...gson-parent-2.6.2) + * Fixed an NPE bug with @JsonAdapter annotation + * Added back OSGI manifest + * Some documentation typo fixes + +## Version 2.6.1 + +_2016-02-11_ [GitHub Diff](https://github.com/google/gson/compare/gson-parent-2.6...gson-parent-2.6.1) + + * Fix: The 2.6 release targeted Java 1.7, but we intend to target Java 1.6. The + 2.6.1 release is identical to 2.6, but it targets Java 1.6. + + +## Version 2.6 + +_2016-02-11_ [GitHub Diff](https://github.com/google/gson/compare/gson-parent-2.5...gson-parent-2.6) + + * Permit timezones without minutes in the default date adapter. + * Update reader and writer for RFC 7159. This means that strings, numbers, + booleans and null may be top-level values in JSON documents, even if the + reader is strict. + * New `setLenient()` method on `GsonBuilder`. This setting impacts the new + factory method `Gson.newJsonReader()`. + * Adapters discovered with `@JsonAdapter` are now null safe by default. + + +## Version 2.5 + +_2015-11-24_ [GitHub Diff](https://github.com/google/gson/compare/gson-parent-2.4...gson-parent-2.5) + + * Updated minimum JDK version to 1.6 + * Improved Date Deserialization by accepting many date formats + * Added support for `java.util.Currency`, `AtomicLong`, `AtomicLongArray`, `AtomicInteger`, `AtomicIntegerArray`, `AtomicBoolean`. This change is backward-incompatible because the earlier version of Gson used the default serialization which wasn't intuitive. We hope that these classes are not used enough to actually cause problems in the field. + * Improved debugging information when some exceptions are thrown + + +## Version 2.4 + +_2015-10-04_ * **Drop `IOException` from `TypeAdapter.toJson()`.** This is a binary-compatible change, but may cause compiler errors where `IOExceptions` are being caught but no longer thrown. The correct fix for this problem is to remove the unnecessary `catch` clause. * New: `Gson.newJsonWriter` method returns configured `JsonWriter` instances. * New: `@SerializedName` now works with [AutoValue’s][autovalue] abstract property methods. + * New: `@SerializedName` permits alternate names when deserializing. * New: `JsonWriter#jsonValue` writes raw JSON values. * New: APIs to add primitives directly to `JsonArray` instances. - * New: ISO 8601 type adapter. Find this in _extras_. + * New: ISO 8601 date type adapter. Find this in _extras_. * Fix: `FieldNamingPolicy` now works properly when running on a device with a Turkish locale. - [autovalue]: https://github.com/google/auto/tree/master/value + +## Version 2.3.1 + +_2014-11-20_ + + * Added support to serialize objects with self-referential fields. The self-referential field is set to null in JSON. Previous version of Gson threw a StackOverflowException on encountering any self-referential fields. + * The most visible impact of this is that Gson can now serialize Throwable (Exception and Error) + * Added support for @JsonAdapter annotation on enums which are user defined types + * Fixed bug in getPath() with array of objects and arrays of arrays + * Other smaller bug fixes + + +## Version 2.3 + +_2014-08-11_ + + * The new @JsonAdapter annotation to specify a Json TypeAdapter for a class field + * JsonPath support: JsonReader.getPath() method returns the JsonPath expression + * New public methods in JsonArray (similar to the java.util.List): `contains(JsonElement), remove(JsonElement), remove(int index), set(int index, JsonElement element)` + * Many other smaller bug fixes + + +## Version 2.2.4 + +_2013-05-13_ + + * Fix internal map (LinkedHashTreeMap) hashing bug. + * Bug fix (Issue 511) + + +## Version 2.2.3 + +_2013-04-12_ + + * Fixes for possible DoS attack due to poor String hashing + + +## Version 2.2.2 + +_2012-07-02_ + + * Gson now allows a user to override default type adapters for Primitives and Strings. This behavior was allowed in earlier versions of Gson but was prohibited started Gson 2.0. We decided to allow it again: This enables a user to parse 1/0 as boolean values for compatibility with iOS JSON libraries. + * (Incompatible behavior change in `JsonParser`): In the past, if `JsonParser` encountered a stream that terminated prematurely, it returned `JsonNull`. This behavior wasn't correct because the stream had invalid JSON, not a null. `JsonParser` is now changed to throw `JsonSyntaxException` in this case. Note that if JsonParser (or Gson) encounter an empty stream, they still return `JsonNull`. + + +## Version 2.2.1 + +_2012-05-05_ + + * Very minor fixes + + +## Version 2.2 + +_2012-05-05_ + + * Added getDelegateAdapter in Gson class + * Fixed a security bug related to denial of service attack with Java HashMap String collisions. + + +## Version 2.1 + +_2011-12-30_ (Targeted Dec 31, 2011) + + * Support for user-defined streaming type adapters + * continued performance enhancements + * Dropped support for type hierarchy instance creators. We don't expect this to be a problem. We'll also detect fewer errors where multiple type adapters can serialize the same type. With APIs like getNextTypeAdapter, this might actually be an improvement! + + +## Version 2.0 + +_2011-11-13_ + +#### Faster + + * Previous versions first parsed complete document into a DOM-style model (JsonObject or JsonArray) and then bound data against that. Gson 2 does data binding directly from the stream parser. + +#### More Predictable + + * Objects are serialized and deserialized in the same way, regardless of where they occur in the object graph. + +#### Changes to watch out for + + * Gson 1.7 would serialize top-level nulls as "". 2.0 serializes them as "null". + ``` + String json = gson.toJson(null, Foo.class); + 1.7: json == "" + 2.0: json == "null" + ``` + + * Gson 1.7 permitted duplicate map keys. 2.0 forbids them. + ``` + String json = "{'a':1,'a':2}"; + Map map = gson.fromJson(json, mapType); + 1.7: map == {a=2} + 2.0: JsonSyntaxException thrown + ``` + + * Gson 1.7 won’t serialize subclass fields in collection elements. 2.0 adds this extra information. + ``` + List points = new ArrayList(); + points.add(new Point3d(1, 2, 3)); + String json = gson.toJson(points, + new TypeToken>() {}.getType()); + 1.7: json == "[{'x':1,'y':2}]" + 2.0: json == "[{'x':1,'y':2,'z':3}]" + ``` + + * Gson 1.7 binds single-element arrays as their contents. 2.0 doesn’t. + ``` + Integer i = gson.fromJson("[42]", Integer.class); + 1.7: i == 42 + 2.0: JsonSyntaxException thrown + ``` + +#### Other changes to be aware of + * Gson 2.0 doesn’t support type adapters for primitive types. + * Gson 1.7 uses arbitrary precision for primitive type conversion (so -122.08e-2132 != 0). Gson 2.0 uses double precision (so -122.08e-2132 == 0). + * Gson 1.7 sets subclass fields when an InstanceCreator returns a subclass when the value is a field of another object. Gson 2.0 sets fields of the requested type only. + * Gson 1.7 versioning never skips the top-level object. Gson 2.0 versioning applies to all objects. + * Gson 1.7 truncates oversized large integers. Gson 2.0 fails on them. + * Gson 2.0 permits integers to have .0 fractions like "1.0". + * Gson 1.7 throws IllegalStateException on circular references. Gson 2.0 lets the runtime throw a StackOverflowError. + + +## Version 1.7.2 + +_2011-09-30_ (Unplanned release) + * Fixed a threading issue in FieldAttributes (Issue 354) + + +## Version 1.7.1 + +_2011-04-13_ (Unplanned release) + + * Fixed Gson jars in Maven Central repository + * Removed assembly-descriptor.xml and maven pom.xml/pom.properties files from Gson binary jar. This also ensures that jarjar can be run correctly on Gson. + + +## Version 1.7 + +_2011-04-12_ (Targeted: Jan 2011) + + * No need to define no-args constructors for classes serialized with Gson + * Ability to register a hierarchical type adapter + * Support for serialization and deserialization of maps with complex keys + * Serialization and deserialization specific exclusion strategies + * Allow concrete data structure fields without type adapters + * Fixes "type" management (i.e. Wildcards, etc.) + * Major performance enhancements by reducing the need for Java reflection +See detailed announcement at this thread in the Gson Google Group. + + +## Version 1.6 + +_2010-11-24_ (Targeted: Oct, 2010) + + * New stream parser APIs + * New parser that improves parsing performance significantly + + +## Version 1.5 + +_2010-08-19_ (Target Date: Aug 18, 2010) + + * Added `UPPER_CAMEL_CASE_WITH_SPACES` naming policy + * Added SQL date and time support + * A number of performance improvements: Using caching of field annotations for speeding up reflection, replacing recursive calls in the parser with a for loop. + + +## Version 1.4 BETA + +_2009_10_09_ + + * JsonStreamParser: A streaming parser API class to deserialize multiple JSON objects on a stream (such as a pipelined HTTP response) + * Raised the deserialization limit for byte and object arrays and collection to over 11MB from 80KB. See issue 96. + * While serializing, Gson now uses the actual type of a field. This allows serialization of base-class references holding sub-classes to the JSON for the sub-class. It also allows serialization of raw collections. See Issue 155, 156. + * Added a `Gson.toJsonTree()` method that serializes a Java object to a tree of JsonElements. See issue 110. + * Added a `Gson.fromJson(JsonElement)` method that deserializes from a Json parse tree. + * Updated `Expose` annotation to contain parameters serialize and deserialize to control whether a field gets serialized or deserialized. See issue 146. + * Added a new naming policy `LOWER_CASE_WITH_DASHES` + * Default date type adapter is now thread-safe. See Issue 162. + * `JsonElement.toString()` now outputs valid JSON after escaping characters properly. See issue 154. + * `JsonPrimitive.equals()` now returns true for two numbers if their values are equal. All integral types (long, int, short, byte, BigDecimal, Long, Integer, Short, Byte) are treated equivalent for comparison. Similarly, floating point types (double, float, BigDecimal, Double, Float) are treated equivalent as well. See issue 147. + * Fixed bugs in pretty printing. See issue 153. + * If a field causes circular reference error, Gson lists the field name instead of the object value. See issue 118. + * Gson now serializes a list with null elements correctly. See issue 117. + * Fixed issue 121, 123, 126. + * Support user defined exclusion strategies (Feature Request 138). + + +## Version 1.3 + +_2009-04-01_ + + * Fix security token to remove the `` element. + * Changed JsonParser.parse method to be non-static + * Throw JsonParseExceptions instead of ClassCastExceptions and UnsupportedOperationExceptions + + +## Version 1.3 beta3 + +_2009-03-17_ + + * Supported custom mapping of field names by making `FieldNamingStrategy` public and allowing `FieldNamingStrategy` to be set in GsonBuilder. See issue 104. + * Added a new GsonBuilder setting `generateNonExecutableJson()` that prefixes the generated JSON with some text to make the output non-executable Javascript. Gson now recognizes this text from input while deserializing and filters it out. This feature is meant to prevent script sourcing attacks. See Issue 42. + * Supported deserialization of sets with elements that do not implement Comparable. See Issue 100 + * Supported deserialization of floating point numbers without a sign after E. See Issue 94 + + +## Version 1.3 beta2 + +_2009-02-05_ + + * Added a new Parser API. See issue 65 + * Supported deserialization of java.util.Properties. See Issue 87 + * Fixed the pretty printing of maps. See Issue 93 + * Supported automatic conversion of strings into numeric and boolean types if possible. See Issue 89 + * Supported deserialization of longs into strings. See Issue 82 + + +## Version 1.3 beta1 + +_2009_01_ (Target Date Friday, Dec 15, 2008) + + * Made JSON parser lenient by allowing unquoted member names while parsing. See Issue 41 + * Better precision handling for floating points. See Issue 71, 72 + * Support for deserialization of special double values: NaN, infinity and negative infinity. See Issue 81 + * Backward compatibility issue found with serialization of `Collection` type. See Issue 73 and 83. + * Able to serialize null keys and/or values within a Map. See Issue 77 + * Deserializing non-String value keys for Maps. See Issue 85. + + * Support for clashing field name. See Issue 76. + * Removed the need to invoke instance creator if a deserializer is registered. See issues 37 and 69. + * Added default support for java.util.UUID. See Issue 79 + * Changed `Gson.toJson()` methods to use `Appendable` instead of `Writer`. Issue 52. This requires that clients recompile their source code that uses Gson. + + +## Version 1.2.3 + +_2008-11-15_ (Target Date Friday, Oct 31, 2008) + + * Added support to serialize raw maps. See issue 45 + * Made Gson thread-safe by fixing Issue 63 + * Fixed Issue 68 to allow default type adapters for primitive types to be replaced by custom type adapters. + * Relaxed the JSON parser to accept escaped slash (\/) as a valid character in the string. See Issue 66 + + +## Version 1.2.2 + +_2008-10-14_ (Target Date: None, Unplanned) + + * This version was released to fix Issue 58 which caused a regression bug in version 1.2.1. It includes the contents from the release 1.2.1 + + +## Version 1.2.1 + +_2008-10-13_ (Target Date Friday, Oct 7, 2008) + +**Note:** This release was abandoned since it caused a regression (Issue 58) bug. + + * Includes updated parser for JSON that supports much larger strings. For example, Gson 1.2 failed at parsing a 100k string, Gson 1.2.1 has successfully parsed strings of size 15-20MB. The parser also is faster and consumes less memory since it uses a token match instead of a recursion-based Grammar production match. See Issue 47. + * Gson now supports field names with single quotes ' in addition to double quotes ". See Issue 55. + * Includes bug fixes for issue 46, 49, 51, 53, 54, and 56. + + +## Version 1.2 + +_2008-08-29_ (Target Date Tuesday Aug 26, 2008) + + * Includes support for feature requests 21, 24, 29 + * Includes bug fixes for Issue 22, Issue 23, Issue 25, Issue 26, Issue 32 , Issue 34, Issue 35, Issue 36, Issue 37, Issue 38, Issue 39 + * Performance enhancements (see r137) + * Documentation updates + + +## Version 1.1.1 + +_2008-07-18_ (Target Date Friday, Aug 1, 2008) + + * Includes fixes for Issue 19, Partial fix for Issue 20 + + +## Version 1.1 + +_2008-07-01_ (Target Date Thursday, July 3, 2008) + + * Includes fixes for Issue 9, Issue 16, Issue 18 + + +## Version 1.0.1 + +_2008-06-17_ (Target Date Friday, Jun 13, 2008) + + * Includes fixes for Issue 15, Issue 14, Issue 3, Issue 8 + * Javadoc improvements diff -Nru libgoogle-gson-java-2.4/debian/changelog libgoogle-gson-java-2.8.2/debian/changelog --- libgoogle-gson-java-2.4/debian/changelog 2017-09-16 20:20:53.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/changelog 2018-04-08 17:51:28.000000000 +0000 @@ -1,3 +1,17 @@ +libgoogle-gson-java (2.8.2-1) unstable; urgency=medium + + * Team upload. + * New upstream version 2.8.2. + - Fix FTBFS with Java 9. (Closes: #893238) + * Drop maven.cleanIgnoreRules and maven.publishedRules because they do + nothing. + * Use compat level 11. + * Declare compliance with Debian Policy 4.1.3. + * Install the MANIFEST file with javahelper since the bnd-maven-plugin is not + available. + + -- Markus Koschany Sun, 08 Apr 2018 19:51:28 +0200 + libgoogle-gson-java (2.4-2) unstable; urgency=medium * Team upload. diff -Nru libgoogle-gson-java-2.4/debian/compat libgoogle-gson-java-2.8.2/debian/compat --- libgoogle-gson-java-2.4/debian/compat 2017-09-16 17:48:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/compat 2018-04-08 17:51:28.000000000 +0000 @@ -1 +1 @@ -10 +11 diff -Nru libgoogle-gson-java-2.4/debian/control libgoogle-gson-java-2.8.2/debian/control --- libgoogle-gson-java-2.4/debian/control 2017-09-16 17:49:07.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/control 2018-04-08 17:51:28.000000000 +0000 @@ -3,13 +3,15 @@ Section: java Maintainer: Debian Java Maintainers Uploaders: Jakub Adam , Emmanuel Bourg -Build-Depends: debhelper (>= 10), +Build-Depends: debhelper (>= 11), default-jdk, + javahelper, junit4, + libmaven-bundle-plugin-java, libmaven-javadoc-plugin-java, maven-debian-helper -Standards-Version: 4.1.0 -Vcs-Git: git://anonscm.debian.org/pkg-java/libgoogle-gson-java.git +Standards-Version: 4.1.3 +Vcs-Git: https://anonscm.debian.org/git/pkg-java/libgoogle-gson-java.git Vcs-Browser: https://anonscm.debian.org/cgit/pkg-java/libgoogle-gson-java.git Homepage: https://github.com/google/gson diff -Nru libgoogle-gson-java-2.4/debian/copyright libgoogle-gson-java-2.8.2/debian/copyright --- libgoogle-gson-java-2.4/debian/copyright 2015-11-03 21:44:07.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/copyright 2018-04-08 17:51:28.000000000 +0000 @@ -1,5 +1,6 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Google Gson +Source: https://github.com/google/gson/releases Upstream-Authors: Inderjeet Singh, Trymph Inc. Joel Leitch, Google Inc. diff -Nru libgoogle-gson-java-2.4/debian/libgoogle-gson-java.manifest libgoogle-gson-java-2.8.2/debian/libgoogle-gson-java.manifest --- libgoogle-gson-java-2.4/debian/libgoogle-gson-java.manifest 1970-01-01 00:00:00.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/libgoogle-gson-java.manifest 2018-04-08 17:51:28.000000000 +0000 @@ -0,0 +1,16 @@ +usr/share/java/gson.jar: + Manifest-Version: 1.0 + Archiver-Version: Plexus Archiver + Bnd-LastModified: 1505871752451 + Bundle-ManifestVersion: 2 + Bundle-RequiredExecutionEnvironment: J2SE-1.5, JavaSE-1.6, JavaSE-1.7, JavaSE-1.8 + Bundle-Vendor: Google Gson Project + Import-Package: com.google.gson.annotations + Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.6))" + Bundle-ContactAddress: https://github.com/google/gson + Tool: Bnd-3.1.0.201512181341 + Export-Package: com.google.gson;uses:="com.google.gson.reflect,com.google.gson.stream";version="2.8.2",com.google.gson.annotations;version="2.8.2",com.google.gson.reflect;version="2.8.2",com.google.gson.stream;version="2.8.2" + Bundle-Name: Gson + Bundle-Version: 2.8.2 + Created-By: Apache Maven 3.5.2 + Build-Jdk: 9.0.4 diff -Nru libgoogle-gson-java-2.4/debian/libgoogle-gson-java.poms libgoogle-gson-java-2.8.2/debian/libgoogle-gson-java.poms --- libgoogle-gson-java-2.4/debian/libgoogle-gson-java.poms 2015-11-03 21:48:57.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/libgoogle-gson-java.poms 2018-04-08 17:51:28.000000000 +0000 @@ -30,3 +30,4 @@ gson/pom.xml --no-parent --java-lib metrics/pom.xml --ignore proto/pom.xml --ignore +pom.xml --no-parent diff -Nru libgoogle-gson-java-2.4/debian/maven.cleanIgnoreRules libgoogle-gson-java-2.8.2/debian/maven.cleanIgnoreRules --- libgoogle-gson-java-2.4/debian/maven.cleanIgnoreRules 2015-11-03 21:49:37.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/maven.cleanIgnoreRules 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -# Maven clean ignore rules - ignore some Maven dependencies and plugins -# during the clean phase of a Maven build -# Format of this file is: -# [group] [artifact] [type] [version] [classifier] [scope] -# where each element can be either -# - the exact string, for example org.apache for the group, or 3.1 -# for the version. In this case, the element is simply matched -# and left as it is -# - * (the star character, alone). In this case, anything will -# match and be left as it is. For example, using * on the -# position of the artifact field will match any artifact id -# All elements much match before a rule can be applied -# Example rule: match jar with groupid= junit, artifactid= junit -# and version starting with 3., this dependency is then removed -# from the POM before mvn clean is called -# junit junit jar s/3\\..*/3.x/ - diff -Nru libgoogle-gson-java-2.4/debian/maven.ignoreRules libgoogle-gson-java-2.8.2/debian/maven.ignoreRules --- libgoogle-gson-java-2.4/debian/maven.ignoreRules 2015-11-03 21:48:57.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/maven.ignoreRules 2018-04-08 17:51:28.000000000 +0000 @@ -4,3 +4,5 @@ org.apache.maven.plugins maven-release-plugin * * * * org.apache.maven.plugins maven-source-plugin * * * * org.sonatype.oss oss-parent * * * * +biz.aQute.bnd bnd-maven-plugin * * * * +org.apache.maven.plugins maven-jar-plugin * * * * diff -Nru libgoogle-gson-java-2.4/debian/maven.properties libgoogle-gson-java-2.8.2/debian/maven.properties --- libgoogle-gson-java-2.4/debian/maven.properties 1970-01-01 00:00:00.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/maven.properties 2018-04-08 17:51:28.000000000 +0000 @@ -0,0 +1 @@ +project.build.sourceEncoding=utf-8 diff -Nru libgoogle-gson-java-2.4/debian/maven.publishedRules libgoogle-gson-java-2.8.2/debian/maven.publishedRules --- libgoogle-gson-java-2.4/debian/maven.publishedRules 2015-11-03 21:49:37.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/maven.publishedRules 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -# Maven published rules - additional rules to publish, to help -# the packaging work of Debian maintainers using mh_make -# Format of this file is: -# [group] [artifact] [type] [version] [classifier] [scope] -# where each element can be either -# - the exact string, for example org.apache for the group, or 3.1 -# for the version. In this case, the element is simply matched -# and left as it is -# - * (the star character, alone). In this case, anything will -# match and be left as it is. For example, using * on the -# position of the artifact field will match any artifact id -# - a regular expression of the form s/match/replace/ -# in this case, elements that match are transformed using -# the regex rule. -# All elements much match before a rule can be applied -# Example rule: match jar with groupid= junit, artifactid= junit -# and version starting with 3., replacing the version with 3.x -# junit junit jar s/3\\..*/3.x/ - diff -Nru libgoogle-gson-java-2.4/debian/patches/java9-dateformat.patch libgoogle-gson-java-2.8.2/debian/patches/java9-dateformat.patch --- libgoogle-gson-java-2.4/debian/patches/java9-dateformat.patch 1970-01-01 00:00:00.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/patches/java9-dateformat.patch 2018-04-08 17:51:28.000000000 +0000 @@ -0,0 +1,552 @@ +From 0aaf5ff408a54eb7dc238d3569b5d1cef9273047 Mon Sep 17 00:00:00 2001 +From: Andrey Mogilev +Date: Sat, 30 Dec 2017 02:14:43 +0700 +Subject: [PATCH] fix Java9 DateFormat changes (#1211) + +* fix Java9 DateFormat changes + +* fix Codacy warnings +--- + .../com/google/gson/DefaultDateTypeAdapter.java | 88 ++++++++++++++-------- + .../gson/internal/PreJava9DateFormatProvider.java | 86 +++++++++++++++++++++ + .../google/gson/internal/bind/DateTypeAdapter.java | 37 ++++++--- + .../java/com/google/gson/util/VersionUtils.java | 49 ++++++++++++ + .../google/gson/DefaultDateTypeAdapterTest.java | 32 +++++--- + .../gson/functional/DefaultTypeAdaptersTest.java | 20 ++++- + .../com/google/gson/functional/ObjectTest.java | 8 +- + 7 files changed, 263 insertions(+), 57 deletions(-) + create mode 100644 gson/src/main/java/com/google/gson/internal/PreJava9DateFormatProvider.java + create mode 100644 gson/src/main/java/com/google/gson/util/VersionUtils.java + +diff --git a/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java b/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java +index 3ce97fe89..0cbf77cea 100644 +--- a/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java ++++ b/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java +@@ -22,13 +22,17 @@ + import java.text.ParseException; + import java.text.ParsePosition; + import java.text.SimpleDateFormat; ++import java.util.ArrayList; + import java.util.Date; ++import java.util.List; + import java.util.Locale; + ++import com.google.gson.internal.PreJava9DateFormatProvider; + import com.google.gson.internal.bind.util.ISO8601Utils; + import com.google.gson.stream.JsonReader; + import com.google.gson.stream.JsonToken; + import com.google.gson.stream.JsonWriter; ++import com.google.gson.util.VersionUtils; + + /** + * This type adapter supports three subclasses of date: Date, Timestamp, and +@@ -42,42 +46,63 @@ + private static final String SIMPLE_NAME = "DefaultDateTypeAdapter"; + + private final Class dateType; +- private final DateFormat enUsFormat; +- private final DateFormat localFormat; +- ++ ++ /** ++ * List of 1 or more different date formats used for de-serialization attempts. ++ * The first of them is used for serialization as well. ++ */ ++ private final List dateFormats = new ArrayList(); ++ + DefaultDateTypeAdapter(Class dateType) { +- this(dateType, +- DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US), +- DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)); ++ this.dateType = verifyDateType(dateType); ++ dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US)); ++ if (!Locale.getDefault().equals(Locale.US)) { ++ dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)); ++ } ++ if (VersionUtils.isJava9OrLater()) { ++ dateFormats.add(PreJava9DateFormatProvider.getUSDateTimeFormat(DateFormat.DEFAULT, DateFormat.DEFAULT)); ++ } + } + + DefaultDateTypeAdapter(Class dateType, String datePattern) { +- this(dateType, new SimpleDateFormat(datePattern, Locale.US), new SimpleDateFormat(datePattern)); ++ this.dateType = verifyDateType(dateType); ++ dateFormats.add(new SimpleDateFormat(datePattern, Locale.US)); ++ if (!Locale.getDefault().equals(Locale.US)) { ++ dateFormats.add(new SimpleDateFormat(datePattern)); ++ } + } + + DefaultDateTypeAdapter(Class dateType, int style) { +- this(dateType, DateFormat.getDateInstance(style, Locale.US), DateFormat.getDateInstance(style)); ++ this.dateType = verifyDateType(dateType); ++ dateFormats.add(DateFormat.getDateInstance(style, Locale.US)); ++ if (!Locale.getDefault().equals(Locale.US)) { ++ dateFormats.add(DateFormat.getDateInstance(style)); ++ } ++ if (VersionUtils.isJava9OrLater()) { ++ dateFormats.add(PreJava9DateFormatProvider.getUSDateFormat(style)); ++ } + } + + public DefaultDateTypeAdapter(int dateStyle, int timeStyle) { +- this(Date.class, +- DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US), +- DateFormat.getDateTimeInstance(dateStyle, timeStyle)); ++ this(Date.class, dateStyle, timeStyle); + } + + public DefaultDateTypeAdapter(Class dateType, int dateStyle, int timeStyle) { +- this(dateType, +- DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US), +- DateFormat.getDateTimeInstance(dateStyle, timeStyle)); ++ this.dateType = verifyDateType(dateType); ++ dateFormats.add(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US)); ++ if (!Locale.getDefault().equals(Locale.US)) { ++ dateFormats.add(DateFormat.getDateTimeInstance(dateStyle, timeStyle)); ++ } ++ if (VersionUtils.isJava9OrLater()) { ++ dateFormats.add(PreJava9DateFormatProvider.getUSDateTimeFormat(dateStyle, timeStyle)); ++ } + } + +- DefaultDateTypeAdapter(final Class dateType, DateFormat enUsFormat, DateFormat localFormat) { ++ private static Class verifyDateType(Class dateType) { + if ( dateType != Date.class && dateType != java.sql.Date.class && dateType != Timestamp.class ) { + throw new IllegalArgumentException("Date type must be one of " + Date.class + ", " + Timestamp.class + ", or " + java.sql.Date.class + " but was " + dateType); + } +- this.dateType = dateType; +- this.enUsFormat = enUsFormat; +- this.localFormat = localFormat; ++ return dateType; + } + + // These methods need to be synchronized since JDK DateFormat classes are not thread-safe +@@ -88,8 +113,8 @@ public void write(JsonWriter out, Date value) throws IOException { + out.nullValue(); + return; + } +- synchronized (localFormat) { +- String dateFormatAsString = enUsFormat.format(value); ++ synchronized(dateFormats) { ++ String dateFormatAsString = dateFormats.get(0).format(value); + out.value(dateFormatAsString); + } + } +@@ -114,13 +139,12 @@ public Date read(JsonReader in) throws IOException { + } + + private Date deserializeToDate(String s) { +- synchronized (localFormat) { +- try { +- return localFormat.parse(s); +- } catch (ParseException ignored) {} +- try { +- return enUsFormat.parse(s); +- } catch (ParseException ignored) {} ++ synchronized (dateFormats) { ++ for (DateFormat dateFormat : dateFormats) { ++ try { ++ return dateFormat.parse(s); ++ } catch (ParseException ignored) {} ++ } + try { + return ISO8601Utils.parse(s, new ParsePosition(0)); + } catch (ParseException e) { +@@ -131,9 +155,11 @@ private Date deserializeToDate(String s) { + + @Override + public String toString() { +- StringBuilder sb = new StringBuilder(); +- sb.append(SIMPLE_NAME); +- sb.append('(').append(localFormat.getClass().getSimpleName()).append(')'); +- return sb.toString(); ++ DateFormat defaultFormat = dateFormats.get(0); ++ if (defaultFormat instanceof SimpleDateFormat) { ++ return SIMPLE_NAME + '(' + ((SimpleDateFormat) defaultFormat).toPattern() + ')'; ++ } else { ++ return SIMPLE_NAME + '(' + defaultFormat.getClass().getSimpleName() + ')'; ++ } + } + } +diff --git a/gson/src/main/java/com/google/gson/internal/PreJava9DateFormatProvider.java b/gson/src/main/java/com/google/gson/internal/PreJava9DateFormatProvider.java +new file mode 100644 +index 000000000..beb527c9e +--- /dev/null ++++ b/gson/src/main/java/com/google/gson/internal/PreJava9DateFormatProvider.java +@@ -0,0 +1,86 @@ ++/* ++ * Copyright (C) 2017 The Gson authors ++ * ++ * 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 com.google.gson.internal; ++ ++import java.text.DateFormat; ++import java.text.SimpleDateFormat; ++import java.util.Locale; ++ ++/** ++ * Provides DateFormats for US locale with patterns which were the default ones before Java 9. ++ */ ++public class PreJava9DateFormatProvider { ++ ++ /** ++ * Returns the same DateFormat as {@code DateFormat.getDateInstance(style, Locale.US)} in Java 8 or below. ++ */ ++ public static DateFormat getUSDateFormat(int style) { ++ return new SimpleDateFormat(getDateFormatPattern(style), Locale.US); ++ } ++ ++ /** ++ * Returns the same DateFormat as {@code DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US)} ++ * in Java 8 or below. ++ */ ++ public static DateFormat getUSDateTimeFormat(int dateStyle, int timeStyle) { ++ String pattern = getDatePartOfDateTimePattern(dateStyle) + " " + getTimePartOfDateTimePattern(timeStyle); ++ return new SimpleDateFormat(pattern, Locale.US); ++ } ++ ++ private static String getDateFormatPattern(int style) { ++ switch (style) { ++ case DateFormat.SHORT: ++ return "M/d/yy"; ++ case DateFormat.MEDIUM: ++ return "MMM d, y"; ++ case DateFormat.LONG: ++ return "MMMM d, y"; ++ case DateFormat.FULL: ++ return "EEEE, MMMM d, y"; ++ default: ++ throw new IllegalArgumentException("Unknown DateFormat style: " + style); ++ } ++ } ++ ++ private static String getDatePartOfDateTimePattern(int dateStyle) { ++ switch (dateStyle) { ++ case DateFormat.SHORT: ++ return "M/d/yy"; ++ case DateFormat.MEDIUM: ++ return "MMM d, yyyy"; ++ case DateFormat.LONG: ++ return "MMMM d, yyyy"; ++ case DateFormat.FULL: ++ return "EEEE, MMMM d, yyyy"; ++ default: ++ throw new IllegalArgumentException("Unknown DateFormat style: " + dateStyle); ++ } ++ } ++ ++ private static String getTimePartOfDateTimePattern(int timeStyle) { ++ switch (timeStyle) { ++ case DateFormat.SHORT: ++ return "h:mm a"; ++ case DateFormat.MEDIUM: ++ return "h:mm:ss a"; ++ case DateFormat.FULL: ++ case DateFormat.LONG: ++ return "h:mm:ss a z"; ++ default: ++ throw new IllegalArgumentException("Unknown DateFormat style: " + timeStyle); ++ } ++ } ++} +diff --git a/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java +index 561af1985..c3a3de1b5 100644 +--- a/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java ++++ b/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java +@@ -20,16 +20,21 @@ + import com.google.gson.JsonSyntaxException; + import com.google.gson.TypeAdapter; + import com.google.gson.TypeAdapterFactory; ++import com.google.gson.internal.PreJava9DateFormatProvider; + import com.google.gson.internal.bind.util.ISO8601Utils; + import com.google.gson.reflect.TypeToken; + import com.google.gson.stream.JsonReader; + import com.google.gson.stream.JsonToken; + import com.google.gson.stream.JsonWriter; ++import com.google.gson.util.VersionUtils; ++ + import java.io.IOException; + import java.text.DateFormat; + import java.text.ParseException; + import java.text.ParsePosition; ++import java.util.ArrayList; + import java.util.Date; ++import java.util.List; + import java.util.Locale; + + /** +@@ -46,10 +51,21 @@ + } + }; + +- private final DateFormat enUsFormat +- = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US); +- private final DateFormat localFormat +- = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT); ++ /** ++ * List of 1 or more different date formats used for de-serialization attempts. ++ * The first of them (default US format) is used for serialization as well. ++ */ ++ private final List dateFormats = new ArrayList(); ++ ++ public DateTypeAdapter() { ++ dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US)); ++ if (!Locale.getDefault().equals(Locale.US)) { ++ dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)); ++ } ++ if (VersionUtils.isJava9OrLater()) { ++ dateFormats.add(PreJava9DateFormatProvider.getUSDateTimeFormat(DateFormat.DEFAULT, DateFormat.DEFAULT)); ++ } ++ } + + @Override public Date read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { +@@ -60,13 +76,10 @@ + } + + private synchronized Date deserializeToDate(String json) { +- try { +- return localFormat.parse(json); +- } catch (ParseException ignored) { +- } +- try { +- return enUsFormat.parse(json); +- } catch (ParseException ignored) { ++ for (DateFormat dateFormat : dateFormats) { ++ try { ++ return dateFormat.parse(json); ++ } catch (ParseException ignored) {} + } + try { + return ISO8601Utils.parse(json, new ParsePosition(0)); +@@ -80,7 +93,7 @@ private synchronized Date deserializeToDate(String json) { + out.nullValue(); + return; + } +- String dateFormatAsString = enUsFormat.format(value); ++ String dateFormatAsString = dateFormats.get(0).format(value); + out.value(dateFormatAsString); + } + +diff --git a/gson/src/main/java/com/google/gson/util/VersionUtils.java b/gson/src/main/java/com/google/gson/util/VersionUtils.java +new file mode 100644 +index 000000000..d81e43c09 +--- /dev/null ++++ b/gson/src/main/java/com/google/gson/util/VersionUtils.java +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (C) 2017 The Gson authors ++ * ++ * 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 com.google.gson.util; ++ ++/** ++ * Utility to check the major Java version of the current JVM. ++ */ ++public class VersionUtils { ++ ++ private static final int majorJavaVersion = determineMajorJavaVersion(); ++ ++ private static int determineMajorJavaVersion() { ++ String[] parts = System.getProperty("java.version").split("[._]"); ++ int firstVer = Integer.parseInt(parts[0]); ++ if (firstVer == 1 && parts.length > 1) { ++ return Integer.parseInt(parts[1]); ++ } else { ++ return firstVer; ++ } ++ } ++ ++ /** ++ * @return the major Java version, i.e. '8' for Java 1.8, '9' for Java 9 etc. ++ */ ++ public static int getMajorJavaVersion() { ++ return majorJavaVersion; ++ } ++ ++ /** ++ * @return {@code true} if the application is running on Java 9 or later; and {@code false} otherwise. ++ */ ++ public static boolean isJava9OrLater() { ++ return majorJavaVersion >= 9; ++ } ++} +diff --git a/gson/src/test/java/com/google/gson/DefaultDateTypeAdapterTest.java b/gson/src/test/java/com/google/gson/DefaultDateTypeAdapterTest.java +index 3c787a665..a074bea0c 100644 +--- a/gson/src/test/java/com/google/gson/DefaultDateTypeAdapterTest.java ++++ b/gson/src/test/java/com/google/gson/DefaultDateTypeAdapterTest.java +@@ -22,6 +22,8 @@ + import java.util.Date; + import java.util.Locale; + import java.util.TimeZone; ++ ++import com.google.gson.util.VersionUtils; + import junit.framework.TestCase; + + /** +@@ -45,17 +47,21 @@ private void assertFormattingAlwaysEmitsUsLocale(Locale locale) { + Locale defaultLocale = Locale.getDefault(); + Locale.setDefault(locale); + try { +- assertFormatted("Jan 1, 1970 12:00:00 AM", new DefaultDateTypeAdapter(Date.class)); ++ String afterYearSep = VersionUtils.isJava9OrLater() ? ", " : " "; ++ String afterYearLongSep = VersionUtils.isJava9OrLater() ? " at " : " "; ++ String utcFull = VersionUtils.isJava9OrLater() ? "Coordinated Universal Time" : "UTC"; ++ assertFormatted(String.format("Jan 1, 1970%s12:00:00 AM", afterYearSep), ++ new DefaultDateTypeAdapter(Date.class)); + assertFormatted("1/1/70", new DefaultDateTypeAdapter(Date.class, DateFormat.SHORT)); + assertFormatted("Jan 1, 1970", new DefaultDateTypeAdapter(Date.class, DateFormat.MEDIUM)); + assertFormatted("January 1, 1970", new DefaultDateTypeAdapter(Date.class, DateFormat.LONG)); +- assertFormatted("1/1/70 12:00 AM", ++ assertFormatted(String.format("1/1/70%s12:00 AM", afterYearSep), + new DefaultDateTypeAdapter(DateFormat.SHORT, DateFormat.SHORT)); +- assertFormatted("Jan 1, 1970 12:00:00 AM", ++ assertFormatted(String.format("Jan 1, 1970%s12:00:00 AM", afterYearSep), + new DefaultDateTypeAdapter(DateFormat.MEDIUM, DateFormat.MEDIUM)); +- assertFormatted("January 1, 1970 12:00:00 AM UTC", ++ assertFormatted(String.format("January 1, 1970%s12:00:00 AM UTC", afterYearLongSep), + new DefaultDateTypeAdapter(DateFormat.LONG, DateFormat.LONG)); +- assertFormatted("Thursday, January 1, 1970 12:00:00 AM UTC", ++ assertFormatted(String.format("Thursday, January 1, 1970%s12:00:00 AM %s", afterYearLongSep, utcFull), + new DefaultDateTypeAdapter(DateFormat.FULL, DateFormat.FULL)); + } finally { + TimeZone.setDefault(defaultTimeZone); +@@ -69,17 +75,21 @@ public void testParsingDatesFormattedWithSystemLocale() throws Exception { + Locale defaultLocale = Locale.getDefault(); + Locale.setDefault(Locale.FRANCE); + try { +- assertParsed("1 janv. 1970 00:00:00", new DefaultDateTypeAdapter(Date.class)); ++ String afterYearSep = VersionUtils.isJava9OrLater() ? " à " : " "; ++ assertParsed(String.format("1 janv. 1970%s00:00:00", afterYearSep), ++ new DefaultDateTypeAdapter(Date.class)); + assertParsed("01/01/70", new DefaultDateTypeAdapter(Date.class, DateFormat.SHORT)); + assertParsed("1 janv. 1970", new DefaultDateTypeAdapter(Date.class, DateFormat.MEDIUM)); + assertParsed("1 janvier 1970", new DefaultDateTypeAdapter(Date.class, DateFormat.LONG)); + assertParsed("01/01/70 00:00", + new DefaultDateTypeAdapter(DateFormat.SHORT, DateFormat.SHORT)); +- assertParsed("1 janv. 1970 00:00:00", ++ assertParsed(String.format("1 janv. 1970%s00:00:00", afterYearSep), + new DefaultDateTypeAdapter(DateFormat.MEDIUM, DateFormat.MEDIUM)); +- assertParsed("1 janvier 1970 00:00:00 UTC", ++ assertParsed(String.format("1 janvier 1970%s00:00:00 UTC", afterYearSep), + new DefaultDateTypeAdapter(DateFormat.LONG, DateFormat.LONG)); +- assertParsed("jeudi 1 janvier 1970 00 h 00 UTC", ++ assertParsed(VersionUtils.isJava9OrLater() ? ++ "jeudi 1 janvier 1970 à 00:00:00 Coordinated Universal Time" : ++ "jeudi 1 janvier 1970 00 h 00 UTC", + new DefaultDateTypeAdapter(DateFormat.FULL, DateFormat.FULL)); + } finally { + TimeZone.setDefault(defaultTimeZone); +@@ -117,7 +127,9 @@ public void testFormatUsesDefaultTimezone() throws Exception { + Locale defaultLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + try { +- assertFormatted("Dec 31, 1969 4:00:00 PM", new DefaultDateTypeAdapter(Date.class)); ++ String afterYearSep = VersionUtils.isJava9OrLater() ? ", " : " "; ++ assertFormatted(String.format("Dec 31, 1969%s4:00:00 PM", afterYearSep), ++ new DefaultDateTypeAdapter(Date.class)); + assertParsed("Dec 31, 1969 4:00:00 PM", new DefaultDateTypeAdapter(Date.class)); + } finally { + TimeZone.setDefault(defaultTimeZone); +diff --git a/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java b/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java +index 198667162..635c20887 100644 +--- a/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java ++++ b/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java +@@ -55,6 +55,8 @@ + import java.util.TimeZone; + import java.util.TreeSet; + import java.util.UUID; ++ ++import com.google.gson.util.VersionUtils; + import junit.framework.TestCase; + + /** +@@ -328,7 +330,11 @@ public void testBitSetDeserialization() throws Exception { + public void testDefaultDateSerialization() { + Date now = new Date(1315806903103L); + String json = gson.toJson(now); +- assertEquals("\"Sep 11, 2011 10:55:03 PM\"", json); ++ if (VersionUtils.isJava9OrLater()) { ++ assertEquals("\"Sep 11, 2011, 10:55:03 PM\"", json); ++ } else { ++ assertEquals("\"Sep 11, 2011 10:55:03 PM\"", json); ++ } + } + + public void testDefaultDateDeserialization() { +@@ -369,7 +375,11 @@ public void testDefaultJavaSqlDateDeserialization() { + public void testDefaultJavaSqlTimestampSerialization() { + Timestamp now = new java.sql.Timestamp(1259875082000L); + String json = gson.toJson(now); +- assertEquals("\"Dec 3, 2009 1:18:02 PM\"", json); ++ if (VersionUtils.isJava9OrLater()) { ++ assertEquals("\"Dec 3, 2009, 1:18:02 PM\"", json); ++ } else { ++ assertEquals("\"Dec 3, 2009 1:18:02 PM\"", json); ++ } + } + + public void testDefaultJavaSqlTimestampDeserialization() { +@@ -395,7 +405,11 @@ public void testDefaultDateSerializationUsingBuilder() throws Exception { + Gson gson = new GsonBuilder().create(); + Date now = new Date(1315806903103L); + String json = gson.toJson(now); +- assertEquals("\"Sep 11, 2011 10:55:03 PM\"", json); ++ if (VersionUtils.isJava9OrLater()) { ++ assertEquals("\"Sep 11, 2011, 10:55:03 PM\"", json); ++ } else { ++ assertEquals("\"Sep 11, 2011 10:55:03 PM\"", json); ++ } + } + + public void testDefaultDateDeserializationUsingBuilder() throws Exception { +diff --git a/gson/src/test/java/com/google/gson/functional/ObjectTest.java b/gson/src/test/java/com/google/gson/functional/ObjectTest.java +index de1219a6a..cf82457a3 100644 +--- a/gson/src/test/java/com/google/gson/functional/ObjectTest.java ++++ b/gson/src/test/java/com/google/gson/functional/ObjectTest.java +@@ -43,6 +43,8 @@ + import java.util.Locale; + import java.util.Map; + import java.util.TimeZone; ++ ++import com.google.gson.util.VersionUtils; + import junit.framework.TestCase; + + /** +@@ -482,7 +484,11 @@ public void testSingletonLists() { + public void testDateAsMapObjectField() { + HasObjectMap a = new HasObjectMap(); + a.map.put("date", new Date(0)); +- assertEquals("{\"map\":{\"date\":\"Dec 31, 1969 4:00:00 PM\"}}", gson.toJson(a)); ++ if (VersionUtils.isJava9OrLater()) { ++ assertEquals("{\"map\":{\"date\":\"Dec 31, 1969, 4:00:00 PM\"}}", gson.toJson(a)); ++ } else { ++ assertEquals("{\"map\":{\"date\":\"Dec 31, 1969 4:00:00 PM\"}}", gson.toJson(a)); ++ } + } + + public class HasObjectMap { diff -Nru libgoogle-gson-java-2.4/debian/patches/java9-reflection.patch libgoogle-gson-java-2.8.2/debian/patches/java9-reflection.patch --- libgoogle-gson-java-2.4/debian/patches/java9-reflection.patch 1970-01-01 00:00:00.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/patches/java9-reflection.patch 2018-04-08 17:51:28.000000000 +0000 @@ -0,0 +1,276 @@ +From 8445689e4d1159298179580b4e260ed23bb2b9bc Mon Sep 17 00:00:00 2001 +From: Andrey Mogilev +Date: Thu, 4 Jan 2018 02:08:50 +0700 +Subject: [PATCH] Java 9 support: use Unsafe-based reflection in Java 9+ + (#1218) + +* Java 9 support: use Unsafe-based reflection in Java 9+ + +fixes "illegal reflective access" warnings and exceptions + +* fix Codacy warnings + +* improve code quality based on PR review + +* improve code quality based on PR review + +* fix Codacy warning + +* improve code quality based on PR review + +* inlined createReflectionAccessor method +--- + .../gson/internal/ConstructorConstructor.java | 4 +- + .../bind/ReflectiveTypeAdapterFactory.java | 4 +- + .../reflect/PreJava9ReflectionAccessor.java | 36 ++++++++++++ + .../gson/internal/reflect/ReflectionAccessor.java | 54 ++++++++++++++++++ + .../internal/reflect/UnsafeReflectionAccessor.java | 64 ++++++++++++++++++++++ + .../java/com/google/gson/reflect/package-info.java | 2 +- + 6 files changed, 161 insertions(+), 3 deletions(-) + create mode 100644 gson/src/main/java/com/google/gson/internal/reflect/PreJava9ReflectionAccessor.java + create mode 100644 gson/src/main/java/com/google/gson/internal/reflect/ReflectionAccessor.java + create mode 100644 gson/src/main/java/com/google/gson/internal/reflect/UnsafeReflectionAccessor.java + +diff --git a/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java b/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java +index 6d1e7c967..5fab46010 100644 +--- a/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java ++++ b/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java +@@ -40,6 +40,7 @@ + + import com.google.gson.InstanceCreator; + import com.google.gson.JsonIOException; ++import com.google.gson.internal.reflect.ReflectionAccessor; + import com.google.gson.reflect.TypeToken; + + /** +@@ -47,6 +48,7 @@ + */ + public final class ConstructorConstructor { + private final Map> instanceCreators; ++ private final ReflectionAccessor accessor = ReflectionAccessor.getInstance(); + + public ConstructorConstructor(Map> instanceCreators) { + this.instanceCreators = instanceCreators; +@@ -98,7 +100,7 @@ public ConstructorConstructor(Map> instanceCreators) { + try { + final Constructor constructor = rawType.getDeclaredConstructor(); + if (!constructor.isAccessible()) { +- constructor.setAccessible(true); ++ accessor.makeAccessible(constructor); + } + return new ObjectConstructor() { + @SuppressWarnings("unchecked") // T is the same raw type as is requested +diff --git a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java +index 42798d059..777e7dee3 100644 +--- a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java ++++ b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java +@@ -28,6 +28,7 @@ + import com.google.gson.internal.Excluder; + import com.google.gson.internal.ObjectConstructor; + import com.google.gson.internal.Primitives; ++import com.google.gson.internal.reflect.ReflectionAccessor; + import com.google.gson.reflect.TypeToken; + import com.google.gson.stream.JsonReader; + import com.google.gson.stream.JsonToken; +@@ -49,6 +50,7 @@ + private final FieldNamingStrategy fieldNamingPolicy; + private final Excluder excluder; + private final JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory; ++ private final ReflectionAccessor accessor = ReflectionAccessor.getInstance(); + + public ReflectiveTypeAdapterFactory(ConstructorConstructor constructorConstructor, + FieldNamingStrategy fieldNamingPolicy, Excluder excluder, +@@ -154,7 +156,7 @@ static boolean excludeField(Field f, boolean serialize, Excluder excluder) { + if (!serialize && !deserialize) { + continue; + } +- field.setAccessible(true); ++ accessor.makeAccessible(field); + Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType()); + List fieldNames = getFieldNames(field); + BoundField previous = null; +diff --git a/gson/src/main/java/com/google/gson/internal/reflect/PreJava9ReflectionAccessor.java b/gson/src/main/java/com/google/gson/internal/reflect/PreJava9ReflectionAccessor.java +new file mode 100644 +index 000000000..2f006517e +--- /dev/null ++++ b/gson/src/main/java/com/google/gson/internal/reflect/PreJava9ReflectionAccessor.java +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2017 The Gson authors ++ * ++ * 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 com.google.gson.internal.reflect; ++ ++import java.lang.reflect.AccessibleObject; ++ ++/** ++ * A basic implementation of {@link ReflectionAccessor} which is suitable for Java 8 and below. ++ *

++ * This implementation just calls {@link AccessibleObject#setAccessible(boolean) setAccessible(true)}, which worked ++ * fine before Java 9. ++ */ ++final class PreJava9ReflectionAccessor extends ReflectionAccessor { ++ ++ /** ++ * {@inheritDoc} ++ */ ++ @Override ++ public void makeAccessible(AccessibleObject ao) { ++ ao.setAccessible(true); ++ } ++ ++} +diff --git a/gson/src/main/java/com/google/gson/internal/reflect/ReflectionAccessor.java b/gson/src/main/java/com/google/gson/internal/reflect/ReflectionAccessor.java +new file mode 100644 +index 000000000..42230d254 +--- /dev/null ++++ b/gson/src/main/java/com/google/gson/internal/reflect/ReflectionAccessor.java +@@ -0,0 +1,54 @@ ++/* ++ * Copyright (C) 2017 The Gson authors ++ * ++ * 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 com.google.gson.internal.reflect; ++ ++import com.google.gson.util.VersionUtils; ++ ++import java.lang.reflect.AccessibleObject; ++ ++/** ++ * Provides a replacement for {@link AccessibleObject#setAccessible(boolean)}, which may be used to ++ * avoid reflective access issues appeared in Java 9, like {@link java.lang.reflect.InaccessibleObjectException} ++ * thrown or warnings like ++ *

++ *   WARNING: An illegal reflective access operation has occurred
++ *   WARNING: Illegal reflective access by ...
++ * 
++ *

++ * Works both for Java 9 and earlier Java versions. ++ */ ++public abstract class ReflectionAccessor { ++ ++ // the singleton instance, use getInstance() to obtain ++ private static final ReflectionAccessor instance = VersionUtils.getMajorJavaVersion() < 9 ? new PreJava9ReflectionAccessor() : new UnsafeReflectionAccessor(); ++ ++ /** ++ * Does the same as {@code ao.setAccessible(true)}, but never throws ++ * {@link java.lang.reflect.InaccessibleObjectException} ++ */ ++ public abstract void makeAccessible(AccessibleObject ao); ++ ++ /** ++ * Obtains a {@link ReflectionAccessor} instance suitable for the current Java version. ++ *

++ * You may need one a reflective operation in your code throws {@link java.lang.reflect.InaccessibleObjectException}. ++ * In such a case, use {@link ReflectionAccessor#makeAccessible(AccessibleObject)} on a field, method or constructor ++ * (instead of basic {@link AccessibleObject#setAccessible(boolean)}). ++ */ ++ public static ReflectionAccessor getInstance() { ++ return instance; ++ } ++} +diff --git a/gson/src/main/java/com/google/gson/internal/reflect/UnsafeReflectionAccessor.java b/gson/src/main/java/com/google/gson/internal/reflect/UnsafeReflectionAccessor.java +new file mode 100644 +index 000000000..5bc59bd8e +--- /dev/null ++++ b/gson/src/main/java/com/google/gson/internal/reflect/UnsafeReflectionAccessor.java +@@ -0,0 +1,64 @@ ++/* ++ * Copyright (C) 2017 The Gson authors ++ * ++ * 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 com.google.gson.internal.reflect; ++ ++import sun.misc.Unsafe; ++ ++import java.lang.reflect.AccessibleObject; ++import java.lang.reflect.Field; ++ ++/** ++ * An implementation of {@link ReflectionAccessor} based on {@link Unsafe}. ++ *

++ * NOTE: This implementation is designed for Java 9. Although it should work with earlier Java releases, it is better to ++ * use {@link PreJava9ReflectionAccessor} for them. ++ */ ++final class UnsafeReflectionAccessor extends ReflectionAccessor { ++ ++ private final Unsafe theUnsafe = getUnsafeInstance(); ++ private final Field overrideField = getOverrideField(); ++ ++ /** ++ * {@inheritDoc} ++ */ ++ @Override ++ public void makeAccessible(AccessibleObject ao) { ++ if (theUnsafe != null && overrideField != null) { ++ long overrideOffset = theUnsafe.objectFieldOffset(overrideField); ++ theUnsafe.putBoolean(ao, overrideOffset, true); ++ } ++ } ++ ++ private static Unsafe getUnsafeInstance() { ++ try { ++ Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); ++ unsafeField.setAccessible(true); ++ return (Unsafe) unsafeField.get(null); ++ } catch (Exception e) { ++ e.printStackTrace(); ++ return null; ++ } ++ } ++ ++ private static Field getOverrideField() { ++ try { ++ return AccessibleObject.class.getDeclaredField("override"); ++ } catch (NoSuchFieldException e) { ++ e.printStackTrace(); ++ return null; ++ } ++ } ++} +diff --git a/gson/src/main/java/com/google/gson/reflect/package-info.java b/gson/src/main/java/com/google/gson/reflect/package-info.java +index e666c4311..5e43ee9fc 100644 +--- a/gson/src/main/java/com/google/gson/reflect/package-info.java ++++ b/gson/src/main/java/com/google/gson/reflect/package-info.java +@@ -1,6 +1,6 @@ + /** + * This package provides utility classes for finding type information for generic types. +- * ++ * + * @author Inderjeet Singh, Joel Leitch + */ + package com.google.gson.reflect; +\ No newline at end of file diff -Nru libgoogle-gson-java-2.4/debian/patches/series libgoogle-gson-java-2.8.2/debian/patches/series --- libgoogle-gson-java-2.4/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/patches/series 2018-04-08 17:51:28.000000000 +0000 @@ -0,0 +1,2 @@ +java9-dateformat.patch +java9-reflection.patch diff -Nru libgoogle-gson-java-2.4/debian/rules libgoogle-gson-java-2.8.2/debian/rules --- libgoogle-gson-java-2.4/debian/rules 2017-09-16 17:53:53.000000000 +0000 +++ libgoogle-gson-java-2.8.2/debian/rules 2018-04-08 17:51:28.000000000 +0000 @@ -1,17 +1,7 @@ #!/usr/bin/make -f - %: - dh $@ --buildsystem=maven - -override_dh_auto_build: - dh_auto_build -- --file gson/pom.xml - -override_dh_auto_test: - dh_auto_test -- --file gson/pom.xml - -override_dh_auto_install: - dh_auto_install -- --file gson/pom.xml + dh $@ --with javahelper --buildsystem=maven get-orig-source: uscan --force-download --download-current-version --rename diff -Nru libgoogle-gson-java-2.4/examples/android-proguard-example/proguard.cfg libgoogle-gson-java-2.8.2/examples/android-proguard-example/proguard.cfg --- libgoogle-gson-java-2.4/examples/android-proguard-example/proguard.cfg 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/examples/android-proguard-example/proguard.cfg 2017-09-20 01:41:34.000000000 +0000 @@ -1,77 +1,3 @@ -##---------------Begin: proguard configuration common for all Android apps ---------- --optimizationpasses 5 --dontusemixedcaseclassnames --dontskipnonpubliclibraryclasses --dontskipnonpubliclibraryclassmembers --dontpreverify --verbose --dump class_files.txt --printseeds seeds.txt --printusage unused.txt --printmapping mapping.txt --optimizations !code/simplification/arithmetic,!field/*,!class/merging/* - --allowaccessmodification --keepattributes *Annotation* --renamesourcefileattribute SourceFile --keepattributes SourceFile,LineNumberTable --repackageclasses '' - --keep public class * extends android.app.Activity --keep public class * extends android.app.Application --keep public class * extends android.app.Service --keep public class * extends android.content.BroadcastReceiver --keep public class * extends android.content.ContentProvider --keep public class * extends android.app.backup.BackupAgentHelper --keep public class * extends android.preference.Preference --keep public class com.android.vending.licensing.ILicensingService --dontnote com.android.vending.licensing.ILicensingService - -# Explicitly preserve all serialization members. The Serializable interface -# is only a marker interface, so it wouldn't save them. --keepclassmembers class * implements java.io.Serializable { - static final long serialVersionUID; - private static final java.io.ObjectStreamField[] serialPersistentFields; - private void writeObject(java.io.ObjectOutputStream); - private void readObject(java.io.ObjectInputStream); - java.lang.Object writeReplace(); - java.lang.Object readResolve(); -} - -# Preserve all native method names and the names of their classes. --keepclasseswithmembernames class * { - native ; -} - --keepclasseswithmembernames class * { - public (android.content.Context, android.util.AttributeSet); -} - --keepclasseswithmembernames class * { - public (android.content.Context, android.util.AttributeSet, int); -} - -# Preserve static fields of inner classes of R classes that might be accessed -# through introspection. --keepclassmembers class **.R$* { - public static ; -} - -# Preserve the special static methods that are required in all enumeration classes. --keepclassmembers enum * { - public static **[] values(); - public static ** valueOf(java.lang.String); -} - --keep public class * { - public protected *; -} - --keep class * implements android.os.Parcelable { - public static final android.os.Parcelable$Creator *; -} -##---------------End: proguard configuration common for all Android apps ---------- - ##---------------Begin: proguard configuration for Gson ---------- # Gson uses generic type information stored in a class file when working with fields. Proguard # removes such information by default, so configure it to keep all of it. @@ -81,10 +7,16 @@ -keepattributes *Annotation* # Gson specific classes --keep class sun.misc.Unsafe { *; } +-dontwarn sun.misc.** #-keep class com.google.gson.stream.** { *; } # Application classes that will be serialized/deserialized over Gson -keep class com.google.gson.examples.android.model.** { *; } +# Prevent proguard from stripping interface information from TypeAdapterFactory, +# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter) +-keep class * implements com.google.gson.TypeAdapterFactory +-keep class * implements com.google.gson.JsonSerializer +-keep class * implements com.google.gson.JsonDeserializer + ##---------------End: proguard configuration for Gson ---------- diff -Nru libgoogle-gson-java-2.4/examples/android-proguard-example/src/com/google/gson/examples/android/model/LineItem.java libgoogle-gson-java-2.8.2/examples/android-proguard-example/src/com/google/gson/examples/android/model/LineItem.java --- libgoogle-gson-java-2.4/examples/android-proguard-example/src/com/google/gson/examples/android/model/LineItem.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/examples/android-proguard-example/src/com/google/gson/examples/android/model/LineItem.java 2017-09-20 01:41:34.000000000 +0000 @@ -52,6 +52,6 @@ @Override public String toString() { return String.format("(item: %s, qty: %s, price: %.2f %s)", - name, quantity, priceInMicros/(double)1000000, currencyCode); + name, quantity, priceInMicros / 1000000d, currencyCode); } } diff -Nru libgoogle-gson-java-2.4/extras/pom.xml libgoogle-gson-java-2.8.2/extras/pom.xml --- libgoogle-gson-java-2.4/extras/pom.xml 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/extras/pom.xml 2017-09-20 01:41:34.000000000 +0000 @@ -40,10 +40,15 @@ com.google.code.gson gson - 2.3.1 + 2.7 compile + javax.annotation + jsr250-api + 1.0 + + junit junit 3.8.2 @@ -86,16 +91,16 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.5.1 - 1.5 - 1.5 + 1.6 + 1.6 org.apache.maven.plugins maven-jar-plugin - 2.5 + 3.0.2 package @@ -113,7 +118,7 @@ org.apache.maven.plugins maven-source-plugin - 2.4 + 3.0.1 attach-sources @@ -127,7 +132,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.1 + 2.10.4 attach-javadocs @@ -147,7 +152,7 @@ org.apache.maven.plugins maven-eclipse-plugin - 2.9 + 2.10 true true diff -Nru libgoogle-gson-java-2.4/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java libgoogle-gson-java-2.8.2/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java --- libgoogle-gson-java-2.4/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libgoogle-gson-java-2.8.2/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java 2017-09-20 01:41:34.000000000 +0000 @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 Gson Authors + * + * 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 com.google.gson.typeadapters; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import javax.annotation.PostConstruct; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +public class PostConstructAdapterFactory implements TypeAdapterFactory { + // copied from https://gist.github.com/swankjesse/20df26adaf639ed7fd160f145a0b661a + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + for (Class t = type.getRawType(); (t != Object.class) && (t.getSuperclass() != null); t = t.getSuperclass()) { + for (Method m : t.getDeclaredMethods()) { + if (m.isAnnotationPresent(PostConstruct.class)) { + m.setAccessible(true); + TypeAdapter delegate = gson.getDelegateAdapter(this, type); + return new PostConstructAdapter(delegate, m); + } + } + } + return null; + } + + final static class PostConstructAdapter extends TypeAdapter { + private final TypeAdapter delegate; + private final Method method; + + public PostConstructAdapter(TypeAdapter delegate, Method method) { + this.delegate = delegate; + this.method = method; + } + + @Override public T read(JsonReader in) throws IOException { + T result = delegate.read(in); + if (result != null) { + try { + method.invoke(result); + } catch (IllegalAccessException e) { + throw new AssertionError(); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof RuntimeException) throw (RuntimeException) e.getCause(); + throw new RuntimeException(e.getCause()); + } + } + return result; + } + + @Override public void write(JsonWriter out, T value) throws IOException { + delegate.write(out, value); + } + } +} diff -Nru libgoogle-gson-java-2.4/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java libgoogle-gson-java-2.8.2/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java --- libgoogle-gson-java-2.4/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java 2017-09-20 01:41:34.000000000 +0000 @@ -94,11 +94,11 @@ * "Rectangle"}) are configurable. * *

Registering Types

- * Create a {@code RuntimeTypeAdapter} by passing the base type and type field + * Create a {@code RuntimeTypeAdapterFactory} by passing the base type and type field * name to the {@link #of} factory method. If you don't supply an explicit type * field name, {@code "type"} will be used.
   {@code
- *   RuntimeTypeAdapter shapeAdapter
- *       = RuntimeTypeAdapter.of(Shape.class, "type");
+ *   RuntimeTypeAdapterFactory shapeAdapterFactory
+ *       = RuntimeTypeAdapterFactory.of(Shape.class, "type");
  * }
* Next register all of your subtypes. Every subtype must be explicitly * registered. This protects your application from injection attacks. If you @@ -108,14 +108,14 @@ * shapeAdapter.registerSubtype(Circle.class, "Circle"); * shapeAdapter.registerSubtype(Diamond.class, "Diamond"); * } - * Finally, register the type adapter in your application's GSON builder: + * Finally, register the type adapter factory in your application's GSON builder: *
   {@code
  *   Gson gson = new GsonBuilder()
- *       .registerTypeAdapter(Shape.class, shapeAdapter)
+ *       .registerTypeAdapterFactory(shapeAdapterFactory)
  *       .create();
  * }
* Like {@code GsonBuilder}, this API supports chaining:
   {@code
- *   RuntimeTypeAdapter shapeAdapter = RuntimeTypeAdapterFactory.of(Shape.class)
+ *   RuntimeTypeAdapterFactory shapeAdapterFactory = RuntimeTypeAdapterFactory.of(Shape.class)
  *       .registerSubtype(Rectangle.class)
  *       .registerSubtype(Circle.class)
  *       .registerSubtype(Diamond.class);
diff -Nru libgoogle-gson-java-2.4/extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java libgoogle-gson-java-2.8.2/extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java
--- libgoogle-gson-java-2.4/extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java	2015-10-04 00:13:56.000000000 +0000
+++ libgoogle-gson-java-2.8.2/extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java	2017-09-20 01:41:34.000000000 +0000
@@ -229,7 +229,7 @@
     } catch (IllegalArgumentException e) {
       fail = e;
     }
-    String input = (date == null) ? null : ('"' + date + "'");
+    String input = (date == null) ? null : ("'" + date + "'");
     throw new ParseException("Failed to parse date [" + input + "]: " + fail.getMessage(), pos.getIndex());
   }
 
diff -Nru libgoogle-gson-java-2.4/extras/src/test/java/com/google/gson/typeadapters/PostConstructAdapterFactoryTest.java libgoogle-gson-java-2.8.2/extras/src/test/java/com/google/gson/typeadapters/PostConstructAdapterFactoryTest.java
--- libgoogle-gson-java-2.4/extras/src/test/java/com/google/gson/typeadapters/PostConstructAdapterFactoryTest.java	1970-01-01 00:00:00.000000000 +0000
+++ libgoogle-gson-java-2.8.2/extras/src/test/java/com/google/gson/typeadapters/PostConstructAdapterFactoryTest.java	2017-09-20 01:41:34.000000000 +0000
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 Gson Authors
+ *
+ * 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 com.google.gson.typeadapters;
+
+import javax.annotation.PostConstruct;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class PostConstructAdapterFactoryTest extends TestCase {
+    public void test() throws Exception {
+        Gson gson = new GsonBuilder()
+                .registerTypeAdapterFactory(new PostConstructAdapterFactory())
+                .create();
+        gson.fromJson("{\"bread\": \"white\", \"cheese\": \"cheddar\"}", Sandwich.class);
+        try {
+            gson.fromJson("{\"bread\": \"cheesey bread\", \"cheese\": \"swiss\"}", Sandwich.class);
+            fail();
+        } catch (IllegalArgumentException expected) {
+            assertEquals("too cheesey", expected.getMessage());
+        }
+    }
+
+    public void testList() {
+        MultipleSandwiches sandwiches = new MultipleSandwiches(Arrays.asList(
+            new Sandwich("white", "cheddar"),
+            new Sandwich("whole wheat", "swiss")));
+
+        Gson gson = new GsonBuilder().registerTypeAdapterFactory(new PostConstructAdapterFactory()).create();
+
+        // Throws NullPointerException without the fix in https://github.com/google/gson/pull/1103
+        String json = gson.toJson(sandwiches);
+        assertEquals("{\"sandwiches\":[{\"bread\":\"white\",\"cheese\":\"cheddar\"},{\"bread\":\"whole wheat\",\"cheese\":\"swiss\"}]}", json);
+
+        MultipleSandwiches sandwichesFromJson = gson.fromJson(json, MultipleSandwiches.class);
+        assertEquals(sandwiches, sandwichesFromJson);
+    }
+
+    static class Sandwich {
+        public String bread;
+        public String cheese;
+
+        public Sandwich(String bread, String cheese) {
+            this.bread = bread;
+            this.cheese = cheese;
+        }
+
+        @PostConstruct private void validate() {
+            if (bread.equals("cheesey bread") && cheese != null) {
+                throw new IllegalArgumentException("too cheesey");
+            }
+        }
+
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            }
+            if (!(o instanceof Sandwich)) {
+                return false;
+            }
+            final Sandwich other = (Sandwich) o;
+            if (this.bread == null ? other.bread != null : !this.bread.equals(other.bread)) {
+                return false;
+            }
+            if (this.cheese == null ? other.cheese != null : !this.cheese.equals(other.cheese)) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    static class MultipleSandwiches {
+        public List sandwiches;
+
+        public MultipleSandwiches(List sandwiches) {
+            this.sandwiches = sandwiches;
+        }
+
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            }
+            if (!(o instanceof MultipleSandwiches)) {
+                return false;
+            }
+            final MultipleSandwiches other = (MultipleSandwiches) o;
+            if (this.sandwiches == null ? other.sandwiches != null : !this.sandwiches.equals(other.sandwiches)) {
+                return false;
+            }
+            return true;
+        }
+    }
+}
diff -Nru libgoogle-gson-java-2.4/extras/src/test/java/com/google/gson/typeadapters/UtcDateTypeAdapterTest.java libgoogle-gson-java-2.8.2/extras/src/test/java/com/google/gson/typeadapters/UtcDateTypeAdapterTest.java
--- libgoogle-gson-java-2.4/extras/src/test/java/com/google/gson/typeadapters/UtcDateTypeAdapterTest.java	2015-10-04 00:13:56.000000000 +0000
+++ libgoogle-gson-java-2.8.2/extras/src/test/java/com/google/gson/typeadapters/UtcDateTypeAdapterTest.java	2017-09-20 01:41:34.000000000 +0000
@@ -22,6 +22,7 @@
 import java.util.Locale;
 import java.util.TimeZone;
 
+import com.google.gson.JsonParseException;
 import junit.framework.TestCase;
 
 import com.google.gson.Gson;
@@ -76,4 +77,13 @@
     String json = gson.toJson(null, Date.class);
     assertEquals("null", json);
   }
+
+  public void testWellFormedParseException() {
+    try {
+      gson.fromJson("2017-06-20T14:32:30", Date.class);
+      fail("No exception");
+    } catch (JsonParseException exe) {
+      assertEquals(exe.getMessage(), "java.text.ParseException: Failed to parse date ['2017-06-20T14']: 2017-06-20T14");
+    }
+  }
 }
diff -Nru libgoogle-gson-java-2.4/.gitignore libgoogle-gson-java-2.8.2/.gitignore
--- libgoogle-gson-java-2.4/.gitignore	2015-10-04 00:13:56.000000000 +0000
+++ libgoogle-gson-java-2.8.2/.gitignore	2017-09-20 01:41:34.000000000 +0000
@@ -2,7 +2,7 @@
 .project
 .settings
 eclipsebin
-
+target
 */target
 pom.xml.*
 release.properties
diff -Nru libgoogle-gson-java-2.4/gson/bnd.bnd libgoogle-gson-java-2.8.2/gson/bnd.bnd
--- libgoogle-gson-java-2.4/gson/bnd.bnd	1970-01-01 00:00:00.000000000 +0000
+++ libgoogle-gson-java-2.8.2/gson/bnd.bnd	2017-09-20 01:41:34.000000000 +0000
@@ -0,0 +1,14 @@
+Bundle-SymbolicName: com.google.gson
+Bundle-Name: ${project.name}
+Bundle-Description: ${project.description}
+Bundle-Vendor: Google Gson Project
+Bundle-ContactAddress: ${project.parent.url}
+Bundle-RequiredExecutionEnvironment: J2SE-1.5, JavaSE-1.6, JavaSE-1.7, JavaSE-1.8
+
+-removeheaders: Private-Package
+
+-exportcontents:\
+    com.google.gson,\
+    com.google.gson.annotations,\
+    com.google.gson.reflect,\
+    com.google.gson.stream
diff -Nru libgoogle-gson-java-2.4/gson/pom.xml libgoogle-gson-java-2.8.2/gson/pom.xml
--- libgoogle-gson-java-2.4/gson/pom.xml	2015-10-04 00:13:56.000000000 +0000
+++ libgoogle-gson-java-2.8.2/gson/pom.xml	2017-09-20 01:41:34.000000000 +0000
@@ -1,245 +1,61 @@
 
   4.0.0
-  com.google.code.gson
-  gson
-  jar
-  2.4
-  2008
-  Gson
+
   
-    org.sonatype.oss
-    oss-parent
-    9
+    com.google.code.gson
+    gson-parent
+    2.8.2
   
-  https://github.com/google/gson
-  Google Gson library
-  
-    UTF-8
-  
-  
-    
-      The Apache Software License, Version 2.0
-      http://www.apache.org/licenses/LICENSE-2.0.txt
-      repo
-    
-  
-  
-    scm:git:https://github.com/google/gson.git
-    scm:git:https://github.com/google/gson.git
-    https://github.com/google/gson
-    gson-${project.version}
-  
-  
-    Github Issue Tracking
-    https://github.com/google/gson/issues
-  
-  
-    
-      sonatype-nexus-snapshots
-      Sonatype Nexus Snapshots
-      https://oss.sonatype.org/content/repositories/snapshots/
-    
-    
-      sonatype-nexus-staging
-      Nexus Release Repository
-      http://oss.sonatype.org/service/local/staging/deploy/maven2/
-    
-  
-  
-    Google, Inc.
-    http://www.google.com
-  
+
+  gson
+  Gson
+
   
     
       junit
       junit
-      3.8.2
       test
     
   
-  
-    
-    
-      release-sign-artifacts
-      
-        
-          performRelease
-          true
-        
-      
-      
-        
-          
-            org.apache.maven.plugins
-            maven-gpg-plugin
-            1.5
-            
-              
-                sign-artifacts
-                verify
-                
-                  sign
-                
-              
-            
-          
-        
-      
-    
-    
-      doclint-java8-disable
-      
-        [1.8,)
-      
-      
-        
-          
-            org.apache.maven.plugins
-            maven-javadoc-plugin
-            
-              -Xdoclint:none
-            
-          
-        
-      
-    
-  
+
   
-    package
     
       
         org.apache.maven.plugins
-        maven-compiler-plugin
-        3.3
+        maven-javadoc-plugin
         
-          1.5
-          1.5
+          com.google.gson
+          com.google.gson.internal:com.google.gson.internal.bind
+          
+            http://docs.oracle.com/javase/6/docs/api/
+          
         
       
       
-        org.apache.maven.plugins
-        maven-jar-plugin
-        2.6
+        biz.aQute.bnd
+        bnd-maven-plugin
+        3.1.0
         
           
-            package
             
-              jar
+              bnd-process
             
           
         
-        
-          
-            false
-            
-              J2SE-1.5, JavaSE-1.6, JavaSE-1.7, JavaSE-1.8
-              
-              ${project.version}
-              https://github.com/google/gson
-              Google Gson Project
-              ${project.name}
-              ${project.description}
-              .
-              2
-              com.google.gson
-            
-          
-        
       
       
-       
-         org.apache.maven.plugins
-         maven-source-plugin
-         2.4
-         
-           
-             attach-sources
-             verify
-             
-               jar
-             
-           
-         
-         
-           
-             
-               com.google.gson;version="${project.version}"
-               com.google.gson.source
-               2
-               ${project.version}
-             
-           
-         
-       
-       
-         
-         org.apache.maven.plugins
-         maven-javadoc-plugin
-         2.10.3
-         
-           
-             attach-javadocs
-             
-               jar
-             
-           
-         
-         
-           com.google.gson
-           com.google.gson.internal:com.google.gson.internal.bind
-            
-             http://docs.oracle.com/javase/1.5.0/docs/api/
-           
-           true
-           protected
-         
-       
-       
-         org.apache.maven.plugins
-         maven-eclipse-plugin
-         2.10
-         
-           true
-           true
-           
-             ../eclipse-ws/
-           
-           
-             file:///${basedir}/../lib/gson-formatting-styles.xml
-           
-         
-       
-      
         org.apache.maven.plugins
-        maven-release-plugin
-        
+        maven-jar-plugin
         
-          -DenableCiProfile=true
+          
+            ${project.build.outputDirectory}/META-INF/MANIFEST.MF
+          
         
       
       
-        maven-assembly-plugin
-        2.5.5
-        
-          assembly-descriptor.xml
-          google-gson-${project.version}
-          target/dist
-          target/assembly/work
-        
+        org.apache.felix
+        maven-bundle-plugin
       
     
   
-  
-    
-      Inderjeet Singh
-    
-    
-      Joel Leitch
-      Google Inc.
-    
-    
-      Jesse Wilson
-      Square Inc.
-    
-  
 
diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/annotations/Expose.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/annotations/Expose.java
--- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/annotations/Expose.java	2015-10-04 00:13:56.000000000 +0000
+++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/annotations/Expose.java	2017-09-20 01:41:34.000000000 +0000
@@ -16,6 +16,7 @@
 
 package com.google.gson.annotations;
 
+import java.lang.annotation.Documented;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -57,6 +58,7 @@
  * @author Inderjeet Singh
  * @author Joel Leitch
  */
+@Documented
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.FIELD)
 public @interface Expose {
diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/annotations/JsonAdapter.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/annotations/JsonAdapter.java
--- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/annotations/JsonAdapter.java	2015-10-04 00:13:56.000000000 +0000
+++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/annotations/JsonAdapter.java	2017-09-20 01:41:34.000000000 +0000
@@ -16,6 +16,8 @@
 
 package com.google.gson.annotations;
 
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonSerializer;
 import com.google.gson.TypeAdapter;
 import com.google.gson.TypeAdapterFactory;
 import java.lang.annotation.ElementType;
@@ -77,8 +79,10 @@
  * adapters, which in turn take precedence over annotated types.
  *
  * 

The class referenced by this annotation must be either a {@link - * TypeAdapter} or a {@link TypeAdapterFactory}. Using the factory interface - * makes it possible to delegate to the enclosing {@code Gson} instance. + * TypeAdapter} or a {@link TypeAdapterFactory}, or must implement one + * or both of {@link JsonDeserializer} or {@link JsonSerializer}. + * Using {@link TypeAdapterFactory} makes it possible to delegate + * to the enclosing {@code Gson} instance. * * @since 2.3 * @@ -91,7 +95,10 @@ @Target({ElementType.TYPE, ElementType.FIELD}) public @interface JsonAdapter { - /** Either a {@link TypeAdapter} or {@link TypeAdapterFactory}. */ + /** Either a {@link TypeAdapter} or {@link TypeAdapterFactory}, or one or both of {@link JsonDeserializer} or {@link JsonSerializer}. */ Class value(); + /** false, to be able to handle {@code null} values within the adapter, default value is true. */ + boolean nullSafe() default true; + } diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/annotations/SerializedName.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/annotations/SerializedName.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/annotations/SerializedName.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/annotations/SerializedName.java 2017-09-20 01:41:34.000000000 +0000 @@ -16,6 +16,7 @@ package com.google.gson.annotations; +import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -76,14 +77,17 @@ * @author Inderjeet Singh * @author Joel Leitch */ +@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD}) public @interface SerializedName { /** - * @return the desired names of the field when it is deserialized or serialized. All of the specified names will be deserialized from. - * The specified first name is what is used for serialization. + * @return the desired name of the field when it is serialized or deserialized */ String value(); + /** + * @return the alternative names of the field when it is deserialized + */ String[] alternate() default {}; } diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/annotations/Since.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/annotations/Since.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/annotations/Since.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/annotations/Since.java 2017-09-20 01:41:34.000000000 +0000 @@ -16,6 +16,7 @@ package com.google.gson.annotations; +import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -50,6 +51,7 @@ * @author Inderjeet Singh * @author Joel Leitch */ +@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.TYPE}) public @interface Since { diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/annotations/Until.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/annotations/Until.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/annotations/Until.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/annotations/Until.java 2017-09-20 01:41:34.000000000 +0000 @@ -16,6 +16,7 @@ package com.google.gson.annotations; +import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -54,6 +55,7 @@ * @author Joel Leitch * @since 1.3 */ +@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.TYPE}) public @interface Until { diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java 2017-09-20 01:41:34.000000000 +0000 @@ -16,14 +16,19 @@ package com.google.gson; -import java.lang.reflect.Type; +import java.io.IOException; import java.sql.Timestamp; import java.text.DateFormat; import java.text.ParseException; +import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; -import java.util.TimeZone; + +import com.google.gson.internal.bind.util.ISO8601Utils; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; /** * This type adapter supports three subclasses of date: Date, Timestamp, and @@ -32,79 +37,94 @@ * @author Inderjeet Singh * @author Joel Leitch */ -final class DefaultDateTypeAdapter implements JsonSerializer, JsonDeserializer { +final class DefaultDateTypeAdapter extends TypeAdapter { - // TODO: migrate to streaming adapter + private static final String SIMPLE_NAME = "DefaultDateTypeAdapter"; + private final Class dateType; private final DateFormat enUsFormat; private final DateFormat localFormat; - private final DateFormat iso8601Format; - - DefaultDateTypeAdapter() { - this(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US), + + DefaultDateTypeAdapter(Class dateType) { + this(dateType, + DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US), DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)); } - DefaultDateTypeAdapter(String datePattern) { - this(new SimpleDateFormat(datePattern, Locale.US), new SimpleDateFormat(datePattern)); + DefaultDateTypeAdapter(Class dateType, String datePattern) { + this(dateType, new SimpleDateFormat(datePattern, Locale.US), new SimpleDateFormat(datePattern)); } - DefaultDateTypeAdapter(int style) { - this(DateFormat.getDateInstance(style, Locale.US), DateFormat.getDateInstance(style)); + DefaultDateTypeAdapter(Class dateType, int style) { + this(dateType, DateFormat.getDateInstance(style, Locale.US), DateFormat.getDateInstance(style)); } public DefaultDateTypeAdapter(int dateStyle, int timeStyle) { - this(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US), + this(Date.class, + DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US), + DateFormat.getDateTimeInstance(dateStyle, timeStyle)); + } + + public DefaultDateTypeAdapter(Class dateType, int dateStyle, int timeStyle) { + this(dateType, + DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US), DateFormat.getDateTimeInstance(dateStyle, timeStyle)); } - DefaultDateTypeAdapter(DateFormat enUsFormat, DateFormat localFormat) { + DefaultDateTypeAdapter(final Class dateType, DateFormat enUsFormat, DateFormat localFormat) { + if ( dateType != Date.class && dateType != java.sql.Date.class && dateType != Timestamp.class ) { + throw new IllegalArgumentException("Date type must be one of " + Date.class + ", " + Timestamp.class + ", or " + java.sql.Date.class + " but was " + dateType); + } + this.dateType = dateType; 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) { + @Override + public void write(JsonWriter out, Date value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } synchronized (localFormat) { - String dateFormatAsString = enUsFormat.format(src); - return new JsonPrimitive(dateFormatAsString); + String dateFormatAsString = enUsFormat.format(value); + out.value(dateFormatAsString); } } - public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - if (!(json instanceof JsonPrimitive)) { - throw new JsonParseException("The date should be a string value"); + @Override + public Date read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; } - Date date = deserializeToDate(json); - if (typeOfT == Date.class) { + Date date = deserializeToDate(in.nextString()); + if (dateType == Date.class) { return date; - } else if (typeOfT == Timestamp.class) { + } else if (dateType == Timestamp.class) { return new Timestamp(date.getTime()); - } else if (typeOfT == java.sql.Date.class) { + } else if (dateType == java.sql.Date.class) { return new java.sql.Date(date.getTime()); } else { - throw new IllegalArgumentException(getClass() + " cannot deserialize to " + typeOfT); + // This must never happen: dateType is guarded in the primary constructor + throw new AssertionError(); } } - private Date deserializeToDate(JsonElement json) { + private Date deserializeToDate(String s) { synchronized (localFormat) { try { - return localFormat.parse(json.getAsString()); - } catch (ParseException ignored) { - } + return localFormat.parse(s); + } catch (ParseException ignored) {} try { - return enUsFormat.parse(json.getAsString()); - } catch (ParseException ignored) { - } + return enUsFormat.parse(s); + } catch (ParseException ignored) {} try { - return iso8601Format.parse(json.getAsString()); + return ISO8601Utils.parse(s, new ParsePosition(0)); } catch (ParseException e) { - throw new JsonSyntaxException(json.getAsString(), e); + throw new JsonSyntaxException(s, e); } } } @@ -112,7 +132,7 @@ @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append(DefaultDateTypeAdapter.class.getSimpleName()); + sb.append(SIMPLE_NAME); sb.append('(').append(localFormat.getClass().getSimpleName()).append(')'); return sb.toString(); } diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/FieldAttributes.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/FieldAttributes.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/FieldAttributes.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/FieldAttributes.java 2017-09-20 01:41:34.000000000 +0000 @@ -68,7 +68,7 @@ * private List<String> red; * } * - * Type listParmeterizedType = new TypeToken<List<String>>() {}.getType(); + * Type listParameterizedType = new TypeToken<List<String>>() {}.getType(); *

* *

This method would return {@code String.class} for the {@code bar} field and @@ -136,9 +136,13 @@ } /** - * This is exposed internally only for the removing synthetic fields from the JSON output. - * - * @return true if the field is synthetic; otherwise false + * Returns the value of the field represented by this {@code Field}, on + * the specified object. The value is automatically wrapped in an + * object if it has a primitive type. + * + * @return the value of the represented field in object + * {@code obj}; primitive values are wrapped in an appropriate + * object before being returned * @throws IllegalAccessException * @throws IllegalArgumentException */ diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/FieldNamingPolicy.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/FieldNamingPolicy.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/FieldNamingPolicy.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/FieldNamingPolicy.java 2017-09-20 01:41:34.000000000 +0000 @@ -35,7 +35,7 @@ * unchanged. */ IDENTITY() { - public String translateName(Field f) { + @Override public String translateName(Field f) { return f.getName(); } }, @@ -51,7 +51,7 @@ * */ UPPER_CAMEL_CASE() { - public String translateName(Field f) { + @Override public String translateName(Field f) { return upperCaseFirstLetter(f.getName()); } }, @@ -70,7 +70,7 @@ * @since 1.4 */ UPPER_CAMEL_CASE_WITH_SPACES() { - public String translateName(Field f) { + @Override public String translateName(Field f) { return upperCaseFirstLetter(separateCamelCase(f.getName(), " ")); } }, @@ -88,7 +88,7 @@ * */ LOWER_CASE_WITH_UNDERSCORES() { - public String translateName(Field f) { + @Override public String translateName(Field f) { return separateCamelCase(f.getName(), "_").toLowerCase(Locale.ENGLISH); } }, @@ -111,7 +111,7 @@ * @since 1.4 */ LOWER_CASE_WITH_DASHES() { - public String translateName(Field f) { + @Override public String translateName(Field f) { return separateCamelCase(f.getName(), "-").toLowerCase(Locale.ENGLISH); } }; @@ -120,9 +120,9 @@ * Converts the field name that uses camel-case define word separation into * separate words that are separated by the provided {@code separatorString}. */ - private static String separateCamelCase(String name, String separator) { + static String separateCamelCase(String name, String separator) { StringBuilder translation = new StringBuilder(); - for (int i = 0; i < name.length(); i++) { + for (int i = 0, length = name.length(); i < length; i++) { char character = name.charAt(i); if (Character.isUpperCase(character) && translation.length() != 0) { translation.append(separator); @@ -135,12 +135,13 @@ /** * Ensures the JSON field names begins with an upper case letter. */ - private static String upperCaseFirstLetter(String name) { + static String upperCaseFirstLetter(String name) { StringBuilder fieldNameBuilder = new StringBuilder(); int index = 0; char firstCharacter = name.charAt(index); + int length = name.length(); - while (index < name.length() - 1) { + while (index < length - 1) { if (Character.isLetter(firstCharacter)) { break; } @@ -149,10 +150,6 @@ firstCharacter = name.charAt(++index); } - if (index == name.length()) { - return fieldNameBuilder.toString(); - } - if (!Character.isUpperCase(firstCharacter)) { String modifiedTarget = modifyString(Character.toUpperCase(firstCharacter), name, ++index); return fieldNameBuilder.append(modifiedTarget).toString(); @@ -166,4 +163,4 @@ ? firstCharacter + srcString.substring(indexOfSubstring) : String.valueOf(firstCharacter); } -} \ No newline at end of file +} diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/GsonBuilder.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/GsonBuilder.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/GsonBuilder.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/GsonBuilder.java 2017-09-20 01:41:34.000000000 +0000 @@ -28,8 +28,18 @@ import com.google.gson.internal.$Gson$Preconditions; import com.google.gson.internal.Excluder; +import com.google.gson.internal.bind.TreeTypeAdapter; import com.google.gson.internal.bind.TypeAdapters; import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; + +import static com.google.gson.Gson.DEFAULT_COMPLEX_MAP_KEYS; +import static com.google.gson.Gson.DEFAULT_ESCAPE_HTML; +import static com.google.gson.Gson.DEFAULT_JSON_NON_EXECUTABLE; +import static com.google.gson.Gson.DEFAULT_LENIENT; +import static com.google.gson.Gson.DEFAULT_PRETTY_PRINT; +import static com.google.gson.Gson.DEFAULT_SERIALIZE_NULLS; +import static com.google.gson.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES; /** *

Use this builder to construct a {@link Gson} instance when you need to set configuration @@ -74,15 +84,16 @@ private final List factories = new ArrayList(); /** tree-style hierarchy factories. These come after factories for backwards compatibility. */ private final List hierarchyFactories = new ArrayList(); - private boolean serializeNulls; + private boolean serializeNulls = DEFAULT_SERIALIZE_NULLS; private String datePattern; private int dateStyle = DateFormat.DEFAULT; private int timeStyle = DateFormat.DEFAULT; - private boolean complexMapKeySerialization; - private boolean serializeSpecialFloatingPointValues; - private boolean escapeHtmlChars = true; - private boolean prettyPrinting; - private boolean generateNonExecutableJson; + private boolean complexMapKeySerialization = DEFAULT_COMPLEX_MAP_KEYS; + private boolean serializeSpecialFloatingPointValues = DEFAULT_SPECIALIZE_FLOAT_VALUES; + private boolean escapeHtmlChars = DEFAULT_ESCAPE_HTML; + private boolean prettyPrinting = DEFAULT_PRETTY_PRINT; + private boolean generateNonExecutableJson = DEFAULT_JSON_NON_EXECUTABLE; + private boolean lenient = DEFAULT_LENIENT; /** * Creates a GsonBuilder instance that can be used to build Gson with various configuration @@ -293,7 +304,7 @@ * Configures Gson to apply a set of exclusion strategies during both serialization and * deserialization. Each of the {@code strategies} will be applied as a disjunction rule. * This means that if one of the {@code strategies} suggests that a field (or class) should be - * skipped then that field (or object) is skipped during serializaiton/deserialization. + * skipped then that field (or object) is skipped during serialization/deserialization. * * @param strategies the set of strategy object to apply during object (de)serialization. * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern @@ -352,6 +363,19 @@ } /** + * By default, Gson is strict and only accepts JSON as specified by + * RFC 4627. This option makes the parser + * liberal in what it accepts. + * + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @see JsonReader#setLenient(boolean) + */ + public GsonBuilder setLenient() { + lenient = true; + return this; + } + + /** * By default, Gson escapes HTML characters such as < > etc. Use this option to configure * Gson to pass-through HTML characters as is. * @@ -495,8 +519,7 @@ || typeAdapter instanceof JsonDeserializer || typeAdapter instanceof TypeAdapter); if (typeAdapter instanceof JsonDeserializer || typeAdapter instanceof JsonSerializer) { - hierarchyFactories.add(0, - TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter)); + hierarchyFactories.add(TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter)); } if (typeAdapter instanceof TypeAdapter) { factories.add(TypeAdapters.newTypeHierarchyFactory(baseType, (TypeAdapter)typeAdapter)); @@ -536,31 +559,42 @@ * @return an instance of Gson configured with the options currently set in this builder */ public Gson create() { - List factories = new ArrayList(); + List factories = new ArrayList(this.factories.size() + this.hierarchyFactories.size() + 3); factories.addAll(this.factories); Collections.reverse(factories); - factories.addAll(this.hierarchyFactories); + + List hierarchyFactories = new ArrayList(this.hierarchyFactories); + Collections.reverse(hierarchyFactories); + factories.addAll(hierarchyFactories); + addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories); return new Gson(excluder, fieldNamingPolicy, instanceCreators, serializeNulls, complexMapKeySerialization, - generateNonExecutableJson, escapeHtmlChars, prettyPrinting, + generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient, serializeSpecialFloatingPointValues, longSerializationPolicy, factories); } + @SuppressWarnings("unchecked") private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle, List factories) { DefaultDateTypeAdapter dateTypeAdapter; + TypeAdapter timestampTypeAdapter; + TypeAdapter javaSqlDateTypeAdapter; if (datePattern != null && !"".equals(datePattern.trim())) { - dateTypeAdapter = new DefaultDateTypeAdapter(datePattern); + dateTypeAdapter = new DefaultDateTypeAdapter(Date.class, datePattern); + timestampTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(Timestamp.class, datePattern); + javaSqlDateTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(java.sql.Date.class, datePattern); } else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) { - dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle); + dateTypeAdapter = new DefaultDateTypeAdapter(Date.class, dateStyle, timeStyle); + timestampTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(Timestamp.class, dateStyle, timeStyle); + javaSqlDateTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(java.sql.Date.class, dateStyle, timeStyle); } else { return; } - factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Date.class), dateTypeAdapter)); - factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Timestamp.class), dateTypeAdapter)); - factories.add(TreeTypeAdapter.newFactory(TypeToken.get(java.sql.Date.class), dateTypeAdapter)); + factories.add(TypeAdapters.newFactory(Date.class, dateTypeAdapter)); + factories.add(TypeAdapters.newFactory(Timestamp.class, timestampTypeAdapter)); + factories.add(TypeAdapters.newFactory(java.sql.Date.class, javaSqlDateTypeAdapter)); } } diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/Gson.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/Gson.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/Gson.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/Gson.java 2017-09-20 01:41:34.000000000 +0000 @@ -30,6 +30,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicLongArray; import com.google.gson.internal.ConstructorConstructor; import com.google.gson.internal.Excluder; @@ -76,7 +79,7 @@ *

If the object that your are serializing/deserializing is a {@code ParameterizedType} * (i.e. contains at least one type parameter and may be an array) then you must use the * {@link #toJson(Object, Type)} or {@link #fromJson(String, Type)} method. Here is an - * example for serializing and deserialing a {@code ParameterizedType}: + * example for serializing and deserializing a {@code ParameterizedType}: * *

  * Type listType = new TypeToken<List<String>>() {}.getType();
@@ -99,7 +102,14 @@
  */
 public final class Gson {
   static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
+  static final boolean DEFAULT_LENIENT = false;
+  static final boolean DEFAULT_PRETTY_PRINT = false;
+  static final boolean DEFAULT_ESCAPE_HTML = true;
+  static final boolean DEFAULT_SERIALIZE_NULLS = false;
+  static final boolean DEFAULT_COMPLEX_MAP_KEYS = false;
+  static final boolean DEFAULT_SPECIALIZE_FLOAT_VALUES = false;
 
+  private static final TypeToken NULL_KEY_SURROGATE = TypeToken.get(Object.class);
   private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
 
   /**
@@ -112,32 +122,19 @@
   private final ThreadLocal, FutureTypeAdapter>> calls
       = new ThreadLocal, FutureTypeAdapter>>();
 
-  private final Map, TypeAdapter> typeTokenCache
-      = Collections.synchronizedMap(new HashMap, TypeAdapter>());
+  private final Map, TypeAdapter> typeTokenCache = new ConcurrentHashMap, TypeAdapter>();
 
   private final List factories;
   private final ConstructorConstructor constructorConstructor;
 
+  private final Excluder excluder;
+  private final FieldNamingStrategy fieldNamingStrategy;
   private final boolean serializeNulls;
   private final boolean htmlSafe;
   private final boolean generateNonExecutableJson;
   private final boolean prettyPrinting;
-
-  final JsonDeserializationContext deserializationContext = new JsonDeserializationContext() {
-    @SuppressWarnings("unchecked")
-	public  T deserialize(JsonElement json, Type typeOfT) throws JsonParseException {
-      return (T) fromJson(json, typeOfT);
-    }
-  };
-
-  final JsonSerializationContext serializationContext = new JsonSerializationContext() {
-    public JsonElement serialize(Object src) {
-      return toJsonTree(src);
-    }
-    public JsonElement serialize(Object src, Type typeOfSrc) {
-      return toJsonTree(src, typeOfSrc);
-    }
-  };
+  private final boolean lenient;
+  private final JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory;
 
   /**
    * Constructs a Gson object with default configuration. The default configuration has the
@@ -175,22 +172,26 @@
    */
   public Gson() {
     this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY,
-        Collections.>emptyMap(), false, false, DEFAULT_JSON_NON_EXECUTABLE,
-        true, false, false, LongSerializationPolicy.DEFAULT,
-        Collections.emptyList());
+        Collections.>emptyMap(), DEFAULT_SERIALIZE_NULLS,
+        DEFAULT_COMPLEX_MAP_KEYS, DEFAULT_JSON_NON_EXECUTABLE, DEFAULT_ESCAPE_HTML,
+        DEFAULT_PRETTY_PRINT, DEFAULT_LENIENT, DEFAULT_SPECIALIZE_FLOAT_VALUES,
+        LongSerializationPolicy.DEFAULT, Collections.emptyList());
   }
 
-  Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingPolicy,
+  Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy,
       final Map> instanceCreators, boolean serializeNulls,
       boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
-      boolean prettyPrinting, boolean serializeSpecialFloatingPointValues,
+      boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
       LongSerializationPolicy longSerializationPolicy,
       List typeAdapterFactories) {
     this.constructorConstructor = new ConstructorConstructor(instanceCreators);
+    this.excluder = excluder;
+    this.fieldNamingStrategy = fieldNamingStrategy;
     this.serializeNulls = serializeNulls;
     this.generateNonExecutableJson = generateNonExecutableGson;
     this.htmlSafe = htmlSafe;
     this.prettyPrinting = prettyPrinting;
+    this.lenient = lenient;
 
     List factories = new ArrayList();
 
@@ -210,13 +211,18 @@
     factories.add(TypeAdapters.BOOLEAN_FACTORY);
     factories.add(TypeAdapters.BYTE_FACTORY);
     factories.add(TypeAdapters.SHORT_FACTORY);
-    factories.add(TypeAdapters.newFactory(long.class, Long.class,
-            longAdapter(longSerializationPolicy)));
+    TypeAdapter longAdapter = longAdapter(longSerializationPolicy);
+    factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter));
     factories.add(TypeAdapters.newFactory(double.class, Double.class,
             doubleAdapter(serializeSpecialFloatingPointValues)));
     factories.add(TypeAdapters.newFactory(float.class, Float.class,
             floatAdapter(serializeSpecialFloatingPointValues)));
     factories.add(TypeAdapters.NUMBER_FACTORY);
+    factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY);
+    factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY);
+    factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter)));
+    factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter)));
+    factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY);
     factories.add(TypeAdapters.CHARACTER_FACTORY);
     factories.add(TypeAdapters.STRING_BUILDER_FACTORY);
     factories.add(TypeAdapters.STRING_BUFFER_FACTORY);
@@ -225,6 +231,7 @@
     factories.add(TypeAdapters.URL_FACTORY);
     factories.add(TypeAdapters.URI_FACTORY);
     factories.add(TypeAdapters.UUID_FACTORY);
+    factories.add(TypeAdapters.CURRENCY_FACTORY);
     factories.add(TypeAdapters.LOCALE_FACTORY);
     factories.add(TypeAdapters.INET_ADDRESS_FACTORY);
     factories.add(TypeAdapters.BIT_SET_FACTORY);
@@ -239,14 +246,31 @@
     // type adapters for composite and user-defined types
     factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
     factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
-    factories.add(new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor));
+    this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
+    factories.add(jsonAdapterFactory);
     factories.add(TypeAdapters.ENUM_FACTORY);
     factories.add(new ReflectiveTypeAdapterFactory(
-        constructorConstructor, fieldNamingPolicy, excluder));
+        constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
 
     this.factories = Collections.unmodifiableList(factories);
   }
 
+  public Excluder excluder() {
+    return excluder;
+  }
+
+  public FieldNamingStrategy fieldNamingStrategy() {
+    return fieldNamingStrategy;
+  }
+
+  public boolean serializeNulls() {
+    return serializeNulls;
+  }
+
+  public boolean htmlSafe() {
+    return htmlSafe;
+  }
+
   private TypeAdapter doubleAdapter(boolean serializeSpecialFloatingPointValues) {
     if (serializeSpecialFloatingPointValues) {
       return TypeAdapters.DOUBLE;
@@ -295,7 +319,7 @@
     };
   }
 
-  private void checkValidFloatingPoint(double value) {
+  static void checkValidFloatingPoint(double value) {
     if (Double.isNaN(value) || Double.isInfinite(value)) {
       throw new IllegalArgumentException(value
           + " is not a valid double value as per JSON specification. To override this"
@@ -303,7 +327,7 @@
     }
   }
 
-  private TypeAdapter longAdapter(LongSerializationPolicy longSerializationPolicy) {
+  private static TypeAdapter longAdapter(LongSerializationPolicy longSerializationPolicy) {
     if (longSerializationPolicy == LongSerializationPolicy.DEFAULT) {
       return TypeAdapters.LONG;
     }
@@ -325,6 +349,45 @@
     };
   }
 
+  private static TypeAdapter atomicLongAdapter(final TypeAdapter longAdapter) {
+    return new TypeAdapter() {
+      @Override public void write(JsonWriter out, AtomicLong value) throws IOException {
+        longAdapter.write(out, value.get());
+      }
+      @Override public AtomicLong read(JsonReader in) throws IOException {
+        Number value = longAdapter.read(in);
+        return new AtomicLong(value.longValue());
+      }
+    }.nullSafe();
+  }
+
+  private static TypeAdapter atomicLongArrayAdapter(final TypeAdapter longAdapter) {
+    return new TypeAdapter() {
+      @Override public void write(JsonWriter out, AtomicLongArray value) throws IOException {
+        out.beginArray();
+        for (int i = 0, length = value.length(); i < length; i++) {
+          longAdapter.write(out, value.get(i));
+        }
+        out.endArray();
+      }
+      @Override public AtomicLongArray read(JsonReader in) throws IOException {
+        List list = new ArrayList();
+        in.beginArray();
+        while (in.hasNext()) {
+            long value = longAdapter.read(in).longValue();
+            list.add(value);
+        }
+        in.endArray();
+        int length = list.size();
+        AtomicLongArray array = new AtomicLongArray(length);
+        for (int i = 0; i < length; ++i) {
+          array.set(i, list.get(i));
+        }
+        return array;
+      }
+    }.nullSafe();
+  }
+
   /**
    * Returns the type adapter for {@code} type.
    *
@@ -333,7 +396,7 @@
    */
   @SuppressWarnings("unchecked")
   public  TypeAdapter getAdapter(TypeToken type) {
-    TypeAdapter cached = typeTokenCache.get(type);
+    TypeAdapter cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
     if (cached != null) {
       return (TypeAdapter) cached;
     }
@@ -387,9 +450,9 @@
    *  class StatsTypeAdapterFactory implements TypeAdapterFactory {
    *    public int numReads = 0;
    *    public int numWrites = 0;
-   *    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
-   *      final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
-   *      return new TypeAdapter<T>() {
+   *    public  TypeAdapter create(Gson gson, TypeToken type) {
+   *      final TypeAdapter delegate = gson.getDelegateAdapter(this, type);
+   *      return new TypeAdapter() {
    *        public void write(JsonWriter out, T value) throws IOException {
    *          ++numWrites;
    *          delegate.write(out, value);
@@ -412,7 +475,7 @@
    *  }
* Note that this call will skip all factories registered before {@code skipPast}. In case of * multiple TypeAdapterFactories registered it is up to the caller of this function to insure - * that the order of registration does not prevent this method from reaching a factory they + * that the order of registration does not prevent this method from reaching a factory they * would expect to reply from this call. * Note that since you can not override type adapter factories for String and Java primitive * types, our stats factory will not count the number of String or primitives that will be @@ -425,12 +488,13 @@ * @since 2.2 */ public TypeAdapter getDelegateAdapter(TypeAdapterFactory skipPast, TypeToken type) { - boolean skipPastFound = false; - // Skip past if and only if the specified factory is present in the factories. - // This is useful because the factories created through JsonAdapter annotations are not - // registered in this list. - if (!factories.contains(skipPast)) skipPastFound = true; + // Hack. If the skipPast factory isn't registered, assume the factory is being requested via + // our @JsonAdapter annotation. + if (!factories.contains(skipPast)) { + skipPast = jsonAdapterFactory; + } + boolean skipPastFound = false; for (TypeAdapterFactory factory : factories) { if (!skipPastFound) { if (factory == skipPast) { @@ -638,7 +702,7 @@ JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer)); toJson(jsonElement, jsonWriter); } catch (IOException e) { - throw new RuntimeException(e); + throw new JsonIOException(e); } } @@ -658,6 +722,15 @@ } /** + * Returns a new JSON reader configured for the settings on this Gson instance. + */ + public JsonReader newJsonReader(Reader reader) { + JsonReader jsonReader = new JsonReader(reader); + jsonReader.setLenient(lenient); + return jsonReader; + } + + /** * Writes the JSON for {@code jsonElement} to {@code writer}. * @throws JsonIOException if there was a problem writing to the writer */ @@ -692,7 +765,8 @@ * @param the type of the desired object * @param json the string from which the object is to be deserialized * @param classOfT the class of T - * @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}. + * @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null} + * or if {@code json} is empty. * @throws JsonSyntaxException if json is not a valid representation for an object of type * classOfT */ @@ -748,7 +822,7 @@ * @since 1.2 */ public T fromJson(Reader json, Class classOfT) throws JsonSyntaxException, JsonIOException { - JsonReader jsonReader = new JsonReader(json); + JsonReader jsonReader = newJsonReader(json); Object object = fromJson(jsonReader, classOfT); assertFullConsumption(object, jsonReader); return Primitives.wrap(classOfT).cast(object); @@ -775,7 +849,7 @@ */ @SuppressWarnings("unchecked") public T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException { - JsonReader jsonReader = new JsonReader(json); + JsonReader jsonReader = newJsonReader(json); T object = (T) fromJson(jsonReader, typeOfT); assertFullConsumption(object, jsonReader); return object; @@ -908,7 +982,7 @@ public String toString() { return new StringBuilder("{serializeNulls:") .append(serializeNulls) - .append("factories:").append(factories) + .append(",factories:").append(factories) .append(",instanceCreators:").append(constructorConstructor) .append("}") .toString(); diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java 2017-09-20 01:41:34.000000000 +0000 @@ -38,7 +38,7 @@ public final class ArrayTypeAdapter extends TypeAdapter { public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { @SuppressWarnings({"unchecked", "rawtypes"}) - public TypeAdapter create(Gson gson, TypeToken typeToken) { + @Override public TypeAdapter create(Gson gson, TypeToken typeToken) { Type type = typeToken.getType(); if (!(type instanceof GenericArrayType || type instanceof Class && ((Class) type).isArray())) { return null; @@ -60,7 +60,7 @@ this.componentType = componentType; } - public Object read(JsonReader in) throws IOException { + @Override public Object read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; @@ -73,8 +73,10 @@ list.add(instance); } in.endArray(); - Object array = Array.newInstance(componentType, list.size()); - for (int i = 0; i < list.size(); i++) { + + int size = list.size(); + Object array = Array.newInstance(componentType, size); + for (int i = 0; i < size; i++) { Array.set(array, i, list.get(i)); } return array; diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java 2017-09-20 01:41:34.000000000 +0000 @@ -40,6 +40,7 @@ this.constructorConstructor = constructorConstructor; } + @Override public TypeAdapter create(Gson gson, TypeToken typeToken) { Type type = typeToken.getType(); @@ -69,7 +70,7 @@ this.constructor = constructor; } - public Collection read(JsonReader in) throws IOException { + @Override public Collection read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; @@ -85,7 +86,7 @@ return collection; } - public void write(JsonWriter out, Collection collection) throws IOException { + @Override public void write(JsonWriter out, Collection collection) throws IOException { if (collection == null) { out.nullValue(); return; diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java 2017-09-20 01:41:34.000000000 +0000 @@ -20,6 +20,7 @@ import com.google.gson.JsonSyntaxException; import com.google.gson.TypeAdapter; import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.bind.util.ISO8601Utils; import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; @@ -27,10 +28,9 @@ import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; -import java.text.SimpleDateFormat; +import java.text.ParsePosition; import java.util.Date; import java.util.Locale; -import java.util.TimeZone; /** * Adapter for Date. Although this class appears stateless, it is not. @@ -41,7 +41,7 @@ public final class DateTypeAdapter extends TypeAdapter { public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal - public TypeAdapter create(Gson gson, TypeToken typeToken) { + @Override public TypeAdapter create(Gson gson, TypeToken typeToken) { return typeToken.getRawType() == Date.class ? (TypeAdapter) new DateTypeAdapter() : null; } }; @@ -50,13 +50,6 @@ = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US); private final DateFormat localFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT); - private final DateFormat iso8601Format = buildIso8601Format(); - - private static DateFormat buildIso8601Format() { - DateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); - iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC")); - return iso8601Format; - } @Override public Date read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { @@ -76,7 +69,7 @@ } catch (ParseException ignored) { } try { - return iso8601Format.parse(json); + return ISO8601Utils.parse(json, new ParsePosition(0)); } catch (ParseException e) { throw new JsonSyntaxException(json, e); } @@ -90,4 +83,6 @@ String dateFormatAsString = enUsFormat.format(value); out.value(dateFormatAsString); } + + } diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java 2017-09-20 01:41:34.000000000 +0000 @@ -17,6 +17,8 @@ package com.google.gson.internal.bind; import com.google.gson.Gson; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonSerializer; import com.google.gson.TypeAdapter; import com.google.gson.TypeAdapterFactory; import com.google.gson.annotations.JsonAdapter; @@ -30,7 +32,6 @@ * @since 2.3 */ public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapterFactory { - private final ConstructorConstructor constructorConstructor; public JsonAdapterAnnotationTypeAdapterFactory(ConstructorConstructor constructorConstructor) { @@ -38,30 +39,45 @@ } @SuppressWarnings("unchecked") + @Override public TypeAdapter create(Gson gson, TypeToken targetType) { - JsonAdapter annotation = targetType.getRawType().getAnnotation(JsonAdapter.class); + Class rawType = targetType.getRawType(); + JsonAdapter annotation = rawType.getAnnotation(JsonAdapter.class); if (annotation == null) { return null; } return (TypeAdapter) getTypeAdapter(constructorConstructor, gson, targetType, annotation); } - @SuppressWarnings("unchecked") // Casts guarded by conditionals. - static TypeAdapter getTypeAdapter(ConstructorConstructor constructorConstructor, Gson gson, - TypeToken fieldType, JsonAdapter annotation) { - Class value = annotation.value(); - if (TypeAdapter.class.isAssignableFrom(value)) { - Class> typeAdapter = (Class>) value; - return constructorConstructor.get(TypeToken.get(typeAdapter)).construct(); + @SuppressWarnings({ "unchecked", "rawtypes" }) // Casts guarded by conditionals. + TypeAdapter getTypeAdapter(ConstructorConstructor constructorConstructor, Gson gson, + TypeToken type, JsonAdapter annotation) { + Object instance = constructorConstructor.get(TypeToken.get(annotation.value())).construct(); + + TypeAdapter typeAdapter; + if (instance instanceof TypeAdapter) { + typeAdapter = (TypeAdapter) instance; + } else if (instance instanceof TypeAdapterFactory) { + typeAdapter = ((TypeAdapterFactory) instance).create(gson, type); + } else if (instance instanceof JsonSerializer || instance instanceof JsonDeserializer) { + JsonSerializer serializer = instance instanceof JsonSerializer + ? (JsonSerializer) instance + : null; + JsonDeserializer deserializer = instance instanceof JsonDeserializer + ? (JsonDeserializer) instance + : null; + typeAdapter = new TreeTypeAdapter(serializer, deserializer, gson, type, null); + } else { + throw new IllegalArgumentException("Invalid attempt to bind an instance of " + + instance.getClass().getName() + " as a @JsonAdapter for " + type.toString() + + ". @JsonAdapter value must be a TypeAdapter, TypeAdapterFactory," + + " JsonSerializer or JsonDeserializer."); } - if (TypeAdapterFactory.class.isAssignableFrom(value)) { - Class typeAdapterFactory = (Class) value; - return constructorConstructor.get(TypeToken.get(typeAdapterFactory)) - .construct() - .create(gson, fieldType); + + if (typeAdapter != null && annotation.nullSafe()) { + typeAdapter = typeAdapter.nullSafe(); } - throw new IllegalArgumentException( - "@JsonAdapter value must be TypeAdapter or TypeAdapterFactory reference."); + return typeAdapter; } } diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java 2017-09-20 01:41:34.000000000 +0000 @@ -25,9 +25,7 @@ import com.google.gson.stream.JsonToken; import java.io.IOException; import java.io.Reader; -import java.util.ArrayList; import java.util.Iterator; -import java.util.List; import java.util.Map; /** @@ -47,35 +45,57 @@ }; private static final Object SENTINEL_CLOSED = new Object(); - private final List stack = new ArrayList(); + /* + * The nesting stack. Using a manual array rather than an ArrayList saves 20%. + */ + private Object[] stack = new Object[32]; + private int stackSize = 0; + + /* + * The path members. It corresponds directly to stack: At indices where the + * stack contains an object (EMPTY_OBJECT, DANGLING_NAME or NONEMPTY_OBJECT), + * pathNames contains the name at this scope. Where it contains an array + * (EMPTY_ARRAY, NONEMPTY_ARRAY) pathIndices contains the current index in + * that array. Otherwise the value is undefined, and we take advantage of that + * by incrementing pathIndices when doing so isn't useful. + */ + private String[] pathNames = new String[32]; + private int[] pathIndices = new int[32]; public JsonTreeReader(JsonElement element) { super(UNREADABLE_READER); - stack.add(element); + push(element); } @Override public void beginArray() throws IOException { expect(JsonToken.BEGIN_ARRAY); JsonArray array = (JsonArray) peekStack(); - stack.add(array.iterator()); + push(array.iterator()); + pathIndices[stackSize - 1] = 0; } @Override public void endArray() throws IOException { expect(JsonToken.END_ARRAY); popStack(); // empty iterator popStack(); // array + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } } @Override public void beginObject() throws IOException { expect(JsonToken.BEGIN_OBJECT); JsonObject object = (JsonObject) peekStack(); - stack.add(object.entrySet().iterator()); + push(object.entrySet().iterator()); } @Override public void endObject() throws IOException { expect(JsonToken.END_OBJECT); popStack(); // empty iterator popStack(); // object + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } } @Override public boolean hasNext() throws IOException { @@ -84,19 +104,19 @@ } @Override public JsonToken peek() throws IOException { - if (stack.isEmpty()) { + if (stackSize == 0) { return JsonToken.END_DOCUMENT; } Object o = peekStack(); if (o instanceof Iterator) { - boolean isObject = stack.get(stack.size() - 2) instanceof JsonObject; + boolean isObject = stack[stackSize - 2] instanceof JsonObject; Iterator iterator = (Iterator) o; if (iterator.hasNext()) { if (isObject) { return JsonToken.NAME; } else { - stack.add(iterator.next()); + push(iterator.next()); return peek(); } } else { @@ -127,16 +147,19 @@ } private Object peekStack() { - return stack.get(stack.size() - 1); + return stack[stackSize - 1]; } private Object popStack() { - return stack.remove(stack.size() - 1); + Object result = stack[--stackSize]; + stack[stackSize] = null; + return result; } private void expect(JsonToken expected) throws IOException { if (peek() != expected) { - throw new IllegalStateException("Expected " + expected + " but was " + peek()); + throw new IllegalStateException( + "Expected " + expected + " but was " + peek() + locationString()); } } @@ -144,71 +167,104 @@ expect(JsonToken.NAME); Iterator i = (Iterator) peekStack(); Map.Entry entry = (Map.Entry) i.next(); - stack.add(entry.getValue()); - return (String) entry.getKey(); + String result = (String) entry.getKey(); + pathNames[stackSize - 1] = result; + push(entry.getValue()); + return result; } @Override public String nextString() throws IOException { JsonToken token = peek(); if (token != JsonToken.STRING && token != JsonToken.NUMBER) { - throw new IllegalStateException("Expected " + JsonToken.STRING + " but was " + token); + throw new IllegalStateException( + "Expected " + JsonToken.STRING + " but was " + token + locationString()); + } + String result = ((JsonPrimitive) popStack()).getAsString(); + if (stackSize > 0) { + pathIndices[stackSize - 1]++; } - return ((JsonPrimitive) popStack()).getAsString(); + return result; } @Override public boolean nextBoolean() throws IOException { expect(JsonToken.BOOLEAN); - return ((JsonPrimitive) popStack()).getAsBoolean(); + boolean result = ((JsonPrimitive) popStack()).getAsBoolean(); + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } + return result; } @Override public void nextNull() throws IOException { expect(JsonToken.NULL); popStack(); + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } } @Override public double nextDouble() throws IOException { JsonToken token = peek(); if (token != JsonToken.NUMBER && token != JsonToken.STRING) { - throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token); + throw new IllegalStateException( + "Expected " + JsonToken.NUMBER + " but was " + token + locationString()); } double result = ((JsonPrimitive) peekStack()).getAsDouble(); if (!isLenient() && (Double.isNaN(result) || Double.isInfinite(result))) { throw new NumberFormatException("JSON forbids NaN and infinities: " + result); } popStack(); + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } return result; } @Override public long nextLong() throws IOException { JsonToken token = peek(); if (token != JsonToken.NUMBER && token != JsonToken.STRING) { - throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token); + throw new IllegalStateException( + "Expected " + JsonToken.NUMBER + " but was " + token + locationString()); } long result = ((JsonPrimitive) peekStack()).getAsLong(); popStack(); + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } return result; } @Override public int nextInt() throws IOException { JsonToken token = peek(); if (token != JsonToken.NUMBER && token != JsonToken.STRING) { - throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token); + throw new IllegalStateException( + "Expected " + JsonToken.NUMBER + " but was " + token + locationString()); } int result = ((JsonPrimitive) peekStack()).getAsInt(); popStack(); + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } return result; } @Override public void close() throws IOException { - stack.clear(); - stack.add(SENTINEL_CLOSED); + stack = new Object[] { SENTINEL_CLOSED }; + stackSize = 1; } @Override public void skipValue() throws IOException { if (peek() == JsonToken.NAME) { nextName(); + pathNames[stackSize - 2] = "null"; } else { popStack(); + if (stackSize > 0) { + pathNames[stackSize - 1] = "null"; + } + } + if (stackSize > 0) { + pathIndices[stackSize - 1]++; } } @@ -220,7 +276,45 @@ expect(JsonToken.NAME); Iterator i = (Iterator) peekStack(); Map.Entry entry = (Map.Entry) i.next(); - stack.add(entry.getValue()); - stack.add(new JsonPrimitive((String)entry.getKey())); + push(entry.getValue()); + push(new JsonPrimitive((String) entry.getKey())); + } + + private void push(Object newTop) { + if (stackSize == stack.length) { + Object[] newStack = new Object[stackSize * 2]; + int[] newPathIndices = new int[stackSize * 2]; + String[] newPathNames = new String[stackSize * 2]; + System.arraycopy(stack, 0, newStack, 0, stackSize); + System.arraycopy(pathIndices, 0, newPathIndices, 0, stackSize); + System.arraycopy(pathNames, 0, newPathNames, 0, stackSize); + stack = newStack; + pathIndices = newPathIndices; + pathNames = newPathNames; + } + stack[stackSize++] = newTop; + } + + @Override public String getPath() { + StringBuilder result = new StringBuilder().append('$'); + for (int i = 0; i < stackSize; i++) { + if (stack[i] instanceof JsonArray) { + if (stack[++i] instanceof Iterator) { + result.append('[').append(pathIndices[i]).append(']'); + } + } else if (stack[i] instanceof JsonObject) { + if (stack[++i] instanceof Iterator) { + result.append('.'); + if (pathNames[i] != null) { + result.append(pathNames[i]); + } + } + } + } + return result.toString(); + } + + private String locationString() { + return " at path " + getPath(); } } diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/JsonTreeWriter.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/JsonTreeWriter.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/JsonTreeWriter.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/JsonTreeWriter.java 2017-09-20 01:41:34.000000000 +0000 @@ -159,6 +159,14 @@ return this; } + @Override public JsonWriter value(Boolean value) throws IOException { + if (value == null) { + return nullValue(); + } + put(new JsonPrimitive(value)); + return this; + } + @Override public JsonWriter value(double value) throws IOException { if (!isLenient() && (Double.isNaN(value) || Double.isInfinite(value))) { throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value); diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java 2017-09-20 01:41:34.000000000 +0000 @@ -104,7 +104,7 @@ */ public final class MapTypeAdapterFactory implements TypeAdapterFactory { private final ConstructorConstructor constructorConstructor; - private final boolean complexMapKeySerialization; + final boolean complexMapKeySerialization; public MapTypeAdapterFactory(ConstructorConstructor constructorConstructor, boolean complexMapKeySerialization) { @@ -112,7 +112,7 @@ this.complexMapKeySerialization = complexMapKeySerialization; } - public TypeAdapter create(Gson gson, TypeToken typeToken) { + @Override public TypeAdapter create(Gson gson, TypeToken typeToken) { Type type = typeToken.getType(); Class rawType = typeToken.getRawType(); @@ -157,7 +157,7 @@ this.constructor = constructor; } - public Map read(JsonReader in) throws IOException { + @Override public Map read(JsonReader in) throws IOException { JsonToken peek = in.peek(); if (peek == JsonToken.NULL) { in.nextNull(); @@ -195,7 +195,7 @@ return map; } - public void write(JsonWriter out, Map map) throws IOException { + @Override public void write(JsonWriter out, Map map) throws IOException { if (map == null) { out.nullValue(); return; @@ -224,7 +224,7 @@ if (hasComplexKeys) { out.beginArray(); - for (int i = 0; i < keys.size(); i++) { + for (int i = 0, size = keys.size(); i < size; i++) { out.beginArray(); // entry array Streams.write(keys.get(i), out); valueTypeAdapter.write(out, values.get(i)); @@ -233,7 +233,7 @@ out.endArray(); } else { out.beginObject(); - for (int i = 0; i < keys.size(); i++) { + for (int i = 0, size = keys.size(); i < size; i++) { JsonElement keyElement = keys.get(i); out.name(keyToString(keyElement)); valueTypeAdapter.write(out, values.get(i)); diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java 2017-09-20 01:41:34.000000000 +0000 @@ -37,7 +37,7 @@ public final class ObjectTypeAdapter extends TypeAdapter { public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { @SuppressWarnings("unchecked") - public TypeAdapter create(Gson gson, TypeToken type) { + @Override public TypeAdapter create(Gson gson, TypeToken type) { if (type.getRawType() == Object.class) { return (TypeAdapter) new ObjectTypeAdapter(gson); } @@ -47,7 +47,7 @@ private final Gson gson; - private ObjectTypeAdapter(Gson gson) { + ObjectTypeAdapter(Gson gson) { this.gson = gson; } diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java 2017-09-20 01:41:34.000000000 +0000 @@ -16,16 +16,6 @@ package com.google.gson.internal.bind; -import static com.google.gson.internal.bind.JsonAdapterAnnotationTypeAdapterFactory.getTypeAdapter; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.Type; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - import com.google.gson.FieldNamingStrategy; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; @@ -42,6 +32,14 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; /** * Type adapter that reflects over the fields and methods of a class. @@ -50,12 +48,15 @@ private final ConstructorConstructor constructorConstructor; private final FieldNamingStrategy fieldNamingPolicy; private final Excluder excluder; + private final JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory; public ReflectiveTypeAdapterFactory(ConstructorConstructor constructorConstructor, - FieldNamingStrategy fieldNamingPolicy, Excluder excluder) { + FieldNamingStrategy fieldNamingPolicy, Excluder excluder, + JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory) { this.constructorConstructor = constructorConstructor; this.fieldNamingPolicy = fieldNamingPolicy; this.excluder = excluder; + this.jsonAdapterFactory = jsonAdapterFactory; } public boolean excludeField(Field f, boolean serialize) { @@ -68,25 +69,27 @@ /** first element holds the default name */ private List getFieldNames(Field f) { - return getFieldName(fieldNamingPolicy, f); - } - - /** first element holds the default name */ - static List getFieldName(FieldNamingStrategy fieldNamingPolicy, Field f) { - SerializedName serializedName = f.getAnnotation(SerializedName.class); - List fieldNames = new LinkedList(); - if (serializedName == null) { - fieldNames.add(fieldNamingPolicy.translateName(f)); - } else { - fieldNames.add(serializedName.value()); - for (String alternate : serializedName.alternate()) { - fieldNames.add(alternate); - } + SerializedName annotation = f.getAnnotation(SerializedName.class); + if (annotation == null) { + String name = fieldNamingPolicy.translateName(f); + return Collections.singletonList(name); + } + + String serializedName = annotation.value(); + String[] alternates = annotation.alternate(); + if (alternates.length == 0) { + return Collections.singletonList(serializedName); + } + + List fieldNames = new ArrayList(alternates.length + 1); + fieldNames.add(serializedName); + for (String alternate : alternates) { + fieldNames.add(alternate); } return fieldNames; } - public TypeAdapter create(Gson gson, final TypeToken type) { + @Override public TypeAdapter create(Gson gson, final TypeToken type) { Class raw = type.getRawType(); if (!Object.class.isAssignableFrom(raw)) { @@ -102,14 +105,23 @@ final TypeToken fieldType, boolean serialize, boolean deserialize) { final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType()); // special casing primitives here saves ~5% on Android... + JsonAdapter annotation = field.getAnnotation(JsonAdapter.class); + TypeAdapter mapped = null; + if (annotation != null) { + mapped = jsonAdapterFactory.getTypeAdapter( + constructorConstructor, context, fieldType, annotation); + } + final boolean jsonAdapterPresent = mapped != null; + if (mapped == null) mapped = context.getAdapter(fieldType); + + final TypeAdapter typeAdapter = mapped; return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) { - final TypeAdapter typeAdapter = getFieldAdapter(context, field, fieldType); @SuppressWarnings({"unchecked", "rawtypes"}) // the type adapter and field type always agree @Override void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException { Object fieldValue = field.get(value); - TypeAdapter t = - new TypeAdapterRuntimeTypeWrapper(context, this.typeAdapter, fieldType.getType()); + TypeAdapter t = jsonAdapterPresent ? typeAdapter + : new TypeAdapterRuntimeTypeWrapper(context, typeAdapter, fieldType.getType()); t.write(writer, fieldValue); } @Override void read(JsonReader reader, Object value) @@ -119,7 +131,7 @@ field.set(value, fieldValue); } } - public boolean writeField(Object value) throws IOException, IllegalAccessException { + @Override public boolean writeField(Object value) throws IOException, IllegalAccessException { if (!serialized) return false; Object fieldValue = field.get(value); return fieldValue != value; // avoid recursion for example for Throwable.cause @@ -127,15 +139,6 @@ }; } - private TypeAdapter getFieldAdapter(Gson gson, Field field, TypeToken fieldType) { - JsonAdapter annotation = field.getAnnotation(JsonAdapter.class); - if (annotation != null) { - TypeAdapter adapter = getTypeAdapter(constructorConstructor, gson, fieldType, annotation); - if (adapter != null) return adapter; - } - return gson.getAdapter(fieldType); - } - private Map getBoundFields(Gson context, TypeToken type, Class raw) { Map result = new LinkedHashMap(); if (raw.isInterface()) { @@ -155,7 +158,7 @@ Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType()); List fieldNames = getFieldNames(field); BoundField previous = null; - for (int i = 0; i < fieldNames.size(); ++i) { + for (int i = 0, size = fieldNames.size(); i < size; ++i) { String name = fieldNames.get(i); if (i != 0) serialize = false; // only serialize the default name BoundField boundField = createBoundField(context, field, name, @@ -193,7 +196,7 @@ private final ObjectConstructor constructor; private final Map boundFields; - private Adapter(ObjectConstructor constructor, Map boundFields) { + Adapter(ObjectConstructor constructor, Map boundFields) { this.constructor = constructor; this.boundFields = boundFields; } @@ -241,7 +244,7 @@ } } } catch (IllegalAccessException e) { - throw new AssertionError(); + throw new AssertionError(e); } out.endObject(); } diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/SqlDateTypeAdapter.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/SqlDateTypeAdapter.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/SqlDateTypeAdapter.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/SqlDateTypeAdapter.java 2017-09-20 01:41:34.000000000 +0000 @@ -38,7 +38,7 @@ public final class SqlDateTypeAdapter extends TypeAdapter { public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal - public TypeAdapter create(Gson gson, TypeToken typeToken) { + @Override public TypeAdapter create(Gson gson, TypeToken typeToken) { return typeToken.getRawType() == java.sql.Date.class ? (TypeAdapter) new SqlDateTypeAdapter() : null; } diff -Nru libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/TimeTypeAdapter.java libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/TimeTypeAdapter.java --- libgoogle-gson-java-2.4/gson/src/main/java/com/google/gson/internal/bind/TimeTypeAdapter.java 2015-10-04 00:13:56.000000000 +0000 +++ libgoogle-gson-java-2.8.2/gson/src/main/java/com/google/gson/internal/bind/TimeTypeAdapter.java 2017-09-20 01:41:34.000000000 +0000 @@ -40,7 +40,7 @@ public final class TimeTypeAdapter extends TypeAdapter