2727import org .elasticsearch .common .util .concurrent .ThreadContext ;
2828
2929import java .nio .charset .Charset ;
30- import java .time .ZoneId ;
31- import java .time .ZonedDateTime ;
32- import java .time .format .DateTimeFormatter ;
33- import java .time .format .DateTimeFormatterBuilder ;
34- import java .time .format .SignStyle ;
3530import java .util .BitSet ;
3631import java .util .Collections ;
37- import java .util .HashMap ;
3832import java .util .Iterator ;
3933import java .util .LinkedHashMap ;
4034import java .util .Locale ;
4539import java .util .regex .Matcher ;
4640import java .util .regex .Pattern ;
4741
48- import static java .time .temporal .ChronoField .DAY_OF_MONTH ;
49- import static java .time .temporal .ChronoField .DAY_OF_WEEK ;
50- import static java .time .temporal .ChronoField .HOUR_OF_DAY ;
51- import static java .time .temporal .ChronoField .MINUTE_OF_HOUR ;
52- import static java .time .temporal .ChronoField .MONTH_OF_YEAR ;
53- import static java .time .temporal .ChronoField .SECOND_OF_MINUTE ;
54- import static java .time .temporal .ChronoField .YEAR ;
55-
5642/**
5743 * A logger that logs deprecation notices.
5844 */
@@ -163,73 +149,14 @@ public void deprecatedAndMaybeLog(final String key, final String msg, final Obje
163149 Build .CURRENT .isSnapshot () ? "-SNAPSHOT" : "" ,
164150 Build .CURRENT .shortHash ());
165151
166- /*
167- * 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
168- * 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
169- * grammar for IMF-fixdate is specified as 'day-name "," SP date1 SP time-of-day SP GMT'. Here, day-name is
170- * (Mon|Tue|Wed|Thu|Fri|Sat|Sun). Then, date1 is 'day SP month SP year' where day is 2DIGIT, month is
171- * (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
172- * hour is 2DIGIT, minute is 2DIGIT, and second is 2DIGIT. Finally, 2DIGIT and 4DIGIT have the obvious definitions.
173- */
174- private static final DateTimeFormatter RFC_7231_DATE_TIME ;
175-
176- static {
177- final Map <Long , String > dow = new HashMap <>();
178- dow .put (1L , "Mon" );
179- dow .put (2L , "Tue" );
180- dow .put (3L , "Wed" );
181- dow .put (4L , "Thu" );
182- dow .put (5L , "Fri" );
183- dow .put (6L , "Sat" );
184- dow .put (7L , "Sun" );
185- final Map <Long , String > moy = new HashMap <>();
186- moy .put (1L , "Jan" );
187- moy .put (2L , "Feb" );
188- moy .put (3L , "Mar" );
189- moy .put (4L , "Apr" );
190- moy .put (5L , "May" );
191- moy .put (6L , "Jun" );
192- moy .put (7L , "Jul" );
193- moy .put (8L , "Aug" );
194- moy .put (9L , "Sep" );
195- moy .put (10L , "Oct" );
196- moy .put (11L , "Nov" );
197- moy .put (12L , "Dec" );
198- RFC_7231_DATE_TIME = new DateTimeFormatterBuilder ()
199- .parseCaseInsensitive ()
200- .parseLenient ()
201- .optionalStart ()
202- .appendText (DAY_OF_WEEK , dow )
203- .appendLiteral (", " )
204- .optionalEnd ()
205- .appendValue (DAY_OF_MONTH , 2 , 2 , SignStyle .NOT_NEGATIVE )
206- .appendLiteral (' ' )
207- .appendText (MONTH_OF_YEAR , moy )
208- .appendLiteral (' ' )
209- .appendValue (YEAR , 4 )
210- .appendLiteral (' ' )
211- .appendValue (HOUR_OF_DAY , 2 )
212- .appendLiteral (':' )
213- .appendValue (MINUTE_OF_HOUR , 2 )
214- .optionalStart ()
215- .appendLiteral (':' )
216- .appendValue (SECOND_OF_MINUTE , 2 )
217- .optionalEnd ()
218- .appendLiteral (' ' )
219- .appendOffset ("+HHMM" , "GMT" )
220- .toFormatter (Locale .getDefault (Locale .Category .FORMAT ));
221- }
222-
223- private static final String STARTUP_TIME = RFC_7231_DATE_TIME .format (ZonedDateTime .now (ZoneId .of ("GMT" )));
224-
225152 /**
226153 * Regular expression to test if a string matches the RFC7234 specification for warning headers. This pattern assumes that the warn code
227154 * is always 299. Further, this pattern assumes that the warn agent represents a version of Elasticsearch including the build hash.
228155 */
229- public static Pattern WARNING_HEADER_PATTERN = Pattern .compile (
156+ public static final Pattern WARNING_HEADER_PATTERN = Pattern .compile (
230157 "299 " + // warn code
231158 "Elasticsearch-\\ d+\\ .\\ d+\\ .\\ d+(?:-(?:alpha|beta|rc)\\ d+)?(?:-SNAPSHOT)?-(?:[a-f0-9]{7}|Unknown) " + // warn agent
232- "\" ((?:\t | |!|[\\ x23-\\ x5B]|[\\ x5D-\\ x7E]|[\\ x80-\\ xFF]|\\ \\ |\\ \\ \" )*)\" " + // quoted warning value, captured
159+ "\" ((?:\t | |!|[\\ x23-\\ x5B]|[\\ x5D-\\ x7E]|[\\ x80-\\ xFF]|\\ \\ |\\ \\ \" )*)\" ( " + // quoted warning value, captured
233160 // quoted RFC 1123 date format
234161 "\" " + // opening quote
235162 "(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), " + // weekday
@@ -238,36 +165,31 @@ public void deprecatedAndMaybeLog(final String key, final String msg, final Obje
238165 "\\ d{4} " + // 4-digit year
239166 "\\ d{2}:\\ d{2}:\\ d{2} " + // (two-digit hour):(two-digit minute):(two-digit second)
240167 "GMT" + // GMT
241- "\" " ); // closing quote
168+ "\" )? " ); // closing quote (optional, since an older version can still send a warn-date)
242169
243170 /**
244171 * Extracts the warning value from the value of a warning header that is formatted according to RFC 7234. That is, given a string
245- * {@code 299 Elasticsearch-6.0.0 "warning value" "Sat, 25 Feb 2017 10:27:43 GMT"}, the return value of this method would be {@code
246- * warning value}.
172+ * {@code 299 Elasticsearch-6.0.0 "warning value"}, the return value of this method would be {@code warning value}.
247173 *
248174 * @param s the value of a warning header formatted according to RFC 7234.
249175 * @return the extracted warning value
250176 */
251177 public static String extractWarningValueFromWarningHeader (final String s ) {
252178 /*
253179 * We know the exact format of the warning header, so to extract the warning value we can skip forward from the front to the first
254- * quote, and skip backwards from the end to the penultimate quote:
255- *
256- * 299 Elasticsearch-6.0.0 "warning value" "Sat, 25, Feb 2017 10:27:43 GMT"
257- * ^ ^ ^
258- * firstQuote penultimateQuote lastQuote
180+ * quote and we know the last quote is at the end of the string
259181 *
260- * We do it this way rather than seeking forward after the first quote because there could be escaped quotes in the warning value
261- * but since there are none in the warning date, we can skip backwards to find the quote that closes the quoted warning value.
182+ * 299 Elasticsearch-6.0.0 "warning value"
183+ * ^ ^
184+ * firstQuote lastQuote
262185 *
263186 * We parse this manually rather than using the capturing regular expression because the regular expression involves a lot of
264187 * backtracking and carries a performance penalty. However, when assertions are enabled, we still use the regular expression to
265188 * verify that we are maintaining the warning header format.
266189 */
267190 final int firstQuote = s .indexOf ('\"' );
268- final int lastQuote = s .lastIndexOf ('\"' );
269- final int penultimateQuote = s .lastIndexOf ('\"' , lastQuote - 1 );
270- final String warningValue = s .substring (firstQuote + 1 , penultimateQuote - 2 );
191+ final int lastQuote = s .length () - 1 ;
192+ final String warningValue = s .substring (firstQuote + 1 , lastQuote );
271193 assert assertWarningValue (s , warningValue );
272194 return warningValue ;
273195 }
@@ -329,9 +251,7 @@ void deprecated(final Set<ThreadContext> threadContexts, final String message, f
329251 * @return a warning value formatted according to RFC 7234
330252 */
331253 public static String formatWarning (final String s ) {
332- return WARNING_PREFIX + " "
333- + "\" " + escapeAndEncode (s ) + "\" " + " "
334- + "\" " + STARTUP_TIME + "\" " ;
254+ return WARNING_PREFIX + " " + "\" " + escapeAndEncode (s ) + "\" " ;
335255 }
336256
337257 /**
@@ -442,7 +362,7 @@ static String encode(final String s) {
442362 int startIndex = i ;
443363 do {
444364 i ++;
445- } while (i < s .length () && ! doesNotNeedEncoding .get (s .charAt (i )));
365+ } while (i < s .length () && doesNotNeedEncoding .get (s .charAt (i )) == false );
446366
447367 final byte [] bytes = s .substring (startIndex , i ).getBytes (UTF_8 );
448368 // noinspection ForLoopReplaceableByForEach
0 commit comments