This is an automated email from the git hooks/post-receive script. apo pushed a commit to branch master in repository libgoogle-gson-java.
commit a92baba1447bbd85dad0cf38ab891763a7c237f5 Author: Markus Koschany <a...@debian.org> Date: Sun Apr 8 01:03:13 2018 +0200 Fix FTBFS with Java 9. --- debian/patches/java9-dateformat.patch | 552 ++++++++++++++++++++++++++++++++++ debian/patches/java9-reflection.patch | 276 +++++++++++++++++ debian/patches/series | 2 + 3 files changed, 830 insertions(+) diff --git a/debian/patches/java9-dateformat.patch b/debian/patches/java9-dateformat.patch new file mode 100644 index 0000000..26add3b --- /dev/null +++ b/debian/patches/java9-dateformat.patch @@ -0,0 +1,552 @@ +From 0aaf5ff408a54eb7dc238d3569b5d1cef9273047 Mon Sep 17 00:00:00 2001 +From: Andrey Mogilev <amogi...@gmail.com> +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<? extends Date> 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<DateFormat> dateFormats = new ArrayList<DateFormat>(); ++ + DefaultDateTypeAdapter(Class<? extends Date> 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<? extends Date> 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<? extends Date> 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<? extends Date> 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<? extends Date> dateType, DateFormat enUsFormat, DateFormat localFormat) { ++ private static Class<? extends Date> verifyDateType(Class<? extends Date> 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<DateFormat> dateFormats = new ArrayList<DateFormat>(); ++ ++ 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 --git a/debian/patches/java9-reflection.patch b/debian/patches/java9-reflection.patch new file mode 100644 index 0000000..ea8ed43 --- /dev/null +++ b/debian/patches/java9-reflection.patch @@ -0,0 +1,276 @@ +From 8445689e4d1159298179580b4e260ed23bb2b9bc Mon Sep 17 00:00:00 2001 +From: Andrey Mogilev <amogi...@gmail.com> +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<Type, InstanceCreator<?>> instanceCreators; ++ private final ReflectionAccessor accessor = ReflectionAccessor.getInstance(); + + public ConstructorConstructor(Map<Type, InstanceCreator<?>> instanceCreators) { + this.instanceCreators = instanceCreators; +@@ -98,7 +100,7 @@ public ConstructorConstructor(Map<Type, InstanceCreator<?>> instanceCreators) { + try { + final Constructor<? super T> constructor = rawType.getDeclaredConstructor(); + if (!constructor.isAccessible()) { +- constructor.setAccessible(true); ++ accessor.makeAccessible(constructor); + } + return new ObjectConstructor<T>() { + @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<String> 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. ++ * <p> ++ * 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 ++ * <pre> ++ * WARNING: An illegal reflective access operation has occurred ++ * WARNING: Illegal reflective access by ... ++ * </pre> ++ * <p/> ++ * 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. ++ * <p> ++ * 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}. ++ * <p> ++ * 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 --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..110a611 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,2 @@ +java9-dateformat.patch +java9-reflection.patch -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/libgoogle-gson-java.git _______________________________________________ pkg-java-commits mailing list pkg-java-comm...@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits