From 7ce06aeb8ca108e45efba3923072766854a90a1e Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Tue, 28 Feb 2017 20:28:07 -0500 Subject: [PATCH] Fix date format in warning headers This commit fixes the date format in warning headers. There is some confusion around whether or not RFC 1123 requires two-digit days. However, the warning header specification very clearly relies on a format that requires two-digit days. This commit removes the usage of RFC 1123 date/time format from Java 8, which allows for one-digit days, in favor of a format that forces two-digit days (it's otherwise identical to RFC 1123 format, it is just fixed width). Relates #23418 --- .../common/logging/DeprecationLogger.java | 73 ++++++++++++++++++- .../rest/yaml/section/DoSectionTests.java | 3 - 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/common/logging/DeprecationLogger.java b/core/src/main/java/org/elasticsearch/common/logging/DeprecationLogger.java index 12f3a5d3be6..8d412a0587b 100644 --- a/core/src/main/java/org/elasticsearch/common/logging/DeprecationLogger.java +++ b/core/src/main/java/org/elasticsearch/common/logging/DeprecationLogger.java @@ -29,14 +29,26 @@ import org.elasticsearch.common.util.concurrent.ThreadContext; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.SignStyle; +import java.util.HashMap; import java.util.Iterator; import java.util.Locale; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static java.time.temporal.ChronoField.DAY_OF_MONTH; +import static java.time.temporal.ChronoField.DAY_OF_WEEK; +import static java.time.temporal.ChronoField.HOUR_OF_DAY; +import static java.time.temporal.ChronoField.MINUTE_OF_HOUR; +import static java.time.temporal.ChronoField.MONTH_OF_YEAR; +import static java.time.temporal.ChronoField.SECOND_OF_MINUTE; +import static java.time.temporal.ChronoField.YEAR; + /** * A logger that logs deprecation notices. */ @@ -128,6 +140,63 @@ public class DeprecationLogger { Build.CURRENT.shortHash()) + "\"%s\" \"%s\""; + /* + * RFC 7234 section 5.5 specifies that the warn-date is a quoted HTTP-date. HTTP-date is defined in RFC 7234 Appendix B as being from + * RFC 7231 section 7.1.1.1. RFC 7231 specifies an HTTP-date as an IMF-fixdate (or an obs-date referring to obsolete formats). The + * grammar for IMF-fixdate is specified as 'day-name "," SP date1 SP time-of-day SP GMT'. Here, day-name is + * (Mon|Tue|Wed|Thu|Fri|Sat|Sun). Then, date1 is 'day SP month SP year' where day is 2DIGIT, month is + * (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec), and year is 4DIGIT. Lastly, time-of-day is 'hour ":" minute ":" second' where + * hour is 2DIGIT, minute is 2DIGIT, and second is 2DIGIT. Finally, 2DIGIT and 4DIGIT have the obvious definitions. + */ + private static final DateTimeFormatter RFC_7231_DATE_TIME; + + static { + final Map dow = new HashMap<>(); + dow.put(1L, "Mon"); + dow.put(2L, "Tue"); + dow.put(3L, "Wed"); + dow.put(4L, "Thu"); + dow.put(5L, "Fri"); + dow.put(6L, "Sat"); + dow.put(7L, "Sun"); + final Map moy = new HashMap<>(); + moy.put(1L, "Jan"); + moy.put(2L, "Feb"); + moy.put(3L, "Mar"); + moy.put(4L, "Apr"); + moy.put(5L, "May"); + moy.put(6L, "Jun"); + moy.put(7L, "Jul"); + moy.put(8L, "Aug"); + moy.put(9L, "Sep"); + moy.put(10L, "Oct"); + moy.put(11L, "Nov"); + moy.put(12L, "Dec"); + RFC_7231_DATE_TIME = new DateTimeFormatterBuilder() + .parseCaseInsensitive() + .parseLenient() + .optionalStart() + .appendText(DAY_OF_WEEK, dow) + .appendLiteral(", ") + .optionalEnd() + .appendValue(DAY_OF_MONTH, 2, 2, SignStyle.NOT_NEGATIVE) + .appendLiteral(' ') + .appendText(MONTH_OF_YEAR, moy) + .appendLiteral(' ') + .appendValue(YEAR, 4) + .appendLiteral(' ') + .appendValue(HOUR_OF_DAY, 2) + .appendLiteral(':') + .appendValue(MINUTE_OF_HOUR, 2) + .optionalStart() + .appendLiteral(':') + .appendValue(SECOND_OF_MINUTE, 2) + .optionalEnd() + .appendLiteral(' ') + .appendOffset("+HHMM", "GMT") + .toFormatter(Locale.getDefault(Locale.Category.FORMAT)); + } + private static final ZoneId GMT = ZoneId.of("GMT"); /** @@ -195,13 +264,13 @@ public class DeprecationLogger { /** * Format a warning string in the proper warning format by prepending a warn code, warn agent, wrapping the warning string in quotes, - * and appending the RFC 1123 date. + * and appending the RFC 7231 date. * * @param s the warning string to format * @return a warning value formatted according to RFC 7234 */ public static String formatWarning(final String s) { - return String.format(Locale.ROOT, WARNING_FORMAT, escape(s), DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(GMT))); + return String.format(Locale.ROOT, WARNING_FORMAT, escape(s), RFC_7231_DATE_TIME.format(ZonedDateTime.now(GMT))); } /** diff --git a/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/section/DoSectionTests.java b/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/section/DoSectionTests.java index 2ff0f56d2b3..982eac4b802 100644 --- a/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/section/DoSectionTests.java +++ b/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/section/DoSectionTests.java @@ -19,8 +19,6 @@ package org.elasticsearch.test.rest.yaml.section; -import org.elasticsearch.Version; -import org.elasticsearch.common.hash.MessageDigests; import org.elasticsearch.common.logging.DeprecationLogger; import org.elasticsearch.common.xcontent.XContent; import org.elasticsearch.common.xcontent.XContentLocation; @@ -29,7 +27,6 @@ import org.elasticsearch.common.xcontent.yaml.YamlXContent; import org.hamcrest.MatcherAssert; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.Map;