diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/CookieDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/CookieDecoder.java
index 137266bbea..040e12d710 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/CookieDecoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/CookieDecoder.java
@@ -18,13 +18,15 @@ package io.netty.handler.codec.http;
import static io.netty.handler.codec.http.CookieUtil.firstInvalidCookieNameOctet;
import static io.netty.handler.codec.http.CookieUtil.firstInvalidCookieValueOctet;
import static io.netty.handler.codec.http.CookieUtil.unwrapValue;
+
+import io.netty.handler.codec.DateFormatter;
import io.netty.handler.codec.http.cookie.CookieHeaderNames;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
-import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
@@ -152,14 +154,10 @@ public final class CookieDecoder {
} else if (CookieHeaderNames.PATH.equalsIgnoreCase(name)) {
path = value;
} else if (CookieHeaderNames.EXPIRES.equalsIgnoreCase(name)) {
- try {
- long maxAgeMillis =
- HttpHeaderDateFormat.get().parse(value).getTime() -
- System.currentTimeMillis();
-
+ Date date = DateFormatter.parseHttpDate(value);
+ if (date != null) {
+ long maxAgeMillis = date.getTime() - System.currentTimeMillis();
maxAge = maxAgeMillis / 1000 + (maxAgeMillis % 1000 != 0? 1 : 0);
- } catch (ParseException e) {
- // Ignore.
}
} else if (CookieHeaderNames.MAX_AGE.equalsIgnoreCase(name)) {
maxAge = Integer.parseInt(value);
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java
index 8e9518b3ef..05650d66c5 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java
@@ -16,6 +16,7 @@
package io.netty.handler.codec.http;
import io.netty.handler.codec.CharSequenceValueConverter;
+import io.netty.handler.codec.DateFormatter;
import io.netty.handler.codec.DefaultHeaders;
import io.netty.handler.codec.DefaultHeaders.NameValidator;
import io.netty.handler.codec.DefaultHeadersImpl;
@@ -391,10 +392,10 @@ public class DefaultHttpHeaders extends HttpHeaders {
return (CharSequence) value;
}
if (value instanceof Date) {
- return HttpHeaderDateFormat.get().format((Date) value);
+ return DateFormatter.format((Date) value);
}
if (value instanceof Calendar) {
- return HttpHeaderDateFormat.get().format(((Calendar) value).getTime());
+ return DateFormatter.format(((Calendar) value).getTime());
}
return value.toString();
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderDateFormat.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderDateFormat.java
index bf717cf021..45de26df61 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderDateFormat.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderDateFormat.java
@@ -16,6 +16,7 @@
package io.netty.handler.codec.http;
import io.netty.util.concurrent.FastThreadLocal;
+import io.netty.handler.codec.DateFormatter;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
@@ -32,7 +33,7 @@ import java.util.TimeZone;
*
Sunday, 06-Nov-94 08:49:37 GMT: obsolete specification
* Sun Nov 6 08:49:37 1994: obsolete specification
*
- * @deprecated Use {@link HttpHeaderDateFormatter} instead
+ * @deprecated Use {@link DateFormatter} instead
*/
@Deprecated
public final class HttpHeaderDateFormat extends SimpleDateFormat {
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaders.java
index 587a20d943..5d27cb1887 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaders.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaders.java
@@ -17,6 +17,7 @@ package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
+import io.netty.handler.codec.DateFormatter;
import io.netty.handler.codec.Headers;
import io.netty.util.AsciiString;
@@ -839,7 +840,11 @@ public abstract class HttpHeaders implements Iterable>
if (value == null) {
throw new ParseException("header not found: " + name, 0);
}
- return HttpHeaderDateFormat.get().parse(value);
+ Date date = DateFormatter.parseHttpDate(value);
+ if (date == null) {
+ throw new ParseException("header can't be parsed into a Date: " + value, 0);
+ }
+ return date;
}
/**
@@ -865,15 +870,8 @@ public abstract class HttpHeaders implements Iterable>
@Deprecated
public static Date getDateHeader(HttpMessage message, CharSequence name, Date defaultValue) {
final String value = getHeader(message, name);
- if (value == null) {
- return defaultValue;
- }
-
- try {
- return HttpHeaderDateFormat.get().parse(value);
- } catch (ParseException ignored) {
- return defaultValue;
- }
+ Date date = DateFormatter.parseHttpDate(value);
+ return date != null ? date : defaultValue;
}
/**
@@ -897,7 +895,7 @@ public abstract class HttpHeaders implements Iterable>
@Deprecated
public static void setDateHeader(HttpMessage message, CharSequence name, Date value) {
if (value != null) {
- message.headers().set(name, HttpHeaderDateFormat.get().format(value));
+ message.headers().set(name, DateFormatter.format(value));
} else {
message.headers().set(name, null);
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/cookie/ClientCookieDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/cookie/ClientCookieDecoder.java
index b76bb25698..cbfe20d40f 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/cookie/ClientCookieDecoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/cookie/ClientCookieDecoder.java
@@ -15,7 +15,7 @@
*/
package io.netty.handler.codec.http.cookie;
-import io.netty.handler.codec.http.HttpHeaderDateFormatter;
+import io.netty.handler.codec.DateFormatter;
import java.util.Date;
@@ -168,7 +168,7 @@ public final class ClientCookieDecoder extends CookieDecoder {
if (maxAge != Long.MIN_VALUE) {
return maxAge;
} else if (isValueDefined(expiresStart, expiresEnd)) {
- Date expiresDate = HttpHeaderDateFormatter.parse(header, expiresStart, expiresEnd);
+ Date expiresDate = DateFormatter.parseHttpDate(header, expiresStart, expiresEnd);
if (expiresDate != null) {
long maxAgeMillis = expiresDate.getTime() - System.currentTimeMillis();
return maxAgeMillis / 1000 + (maxAgeMillis % 1000 != 0 ? 1 : 0);
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/cookie/ServerCookieEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/cookie/ServerCookieEncoder.java
index 2e96d8217b..44cc6c7201 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/cookie/ServerCookieEncoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/cookie/ServerCookieEncoder.java
@@ -21,7 +21,7 @@ import static io.netty.handler.codec.http.cookie.CookieUtil.stringBuilder;
import static io.netty.handler.codec.http.cookie.CookieUtil.stripTrailingSeparator;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
-import io.netty.handler.codec.http.HttpHeaderDateFormatter;
+import io.netty.handler.codec.DateFormatter;
import io.netty.handler.codec.http.HttpConstants;
import io.netty.handler.codec.http.HttpRequest;
@@ -106,7 +106,7 @@ public final class ServerCookieEncoder extends CookieEncoder {
Date expires = new Date(cookie.maxAge() * 1000 + System.currentTimeMillis());
buf.append(CookieHeaderNames.EXPIRES);
buf.append((char) HttpConstants.EQUALS);
- HttpHeaderDateFormatter.append(expires, buf);
+ DateFormatter.append(expires, buf);
buf.append((char) HttpConstants.SEMICOLON);
buf.append((char) HttpConstants.SP);
}
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeaderDateFormatterTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeaderDateFormatterTest.java
deleted file mode 100644
index 24f8b4343e..0000000000
--- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeaderDateFormatterTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2016 The Netty Project
- *
- * The Netty Project licenses this file to you 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 io.netty.handler.codec.http;
-
-import org.junit.Test;
-
-import java.util.Date;
-
-import static org.junit.Assert.*;
-import static io.netty.handler.codec.http.HttpHeaderDateFormatter.*;
-
-public class HttpHeaderDateFormatterTest {
- /**
- * This date is set at "06 Nov 1994 08:49:37 GMT", from
- * examples in RFC documentation
- */
- private static final long TIMESTAMP = 784111777000L;
- private static final Date DATE = new Date(TIMESTAMP);
-
- @Test
- public void testParseWithSingleDigitDay() {
- assertEquals(DATE, parse("Sun, 6 Nov 1994 08:49:37 GMT"));
- }
-
- @Test
- public void testParseWithDoubleDigitDay() {
- assertEquals(DATE, parse("Sun, 06 Nov 1994 08:49:37 GMT"));
- }
-
- @Test
- public void testParseWithDashSeparatorSingleDigitDay() {
- assertEquals(DATE, parse("Sunday, 06-Nov-94 08:49:37 GMT"));
- }
-
- @Test
- public void testParseWithSingleDoubleDigitDay() {
- assertEquals(DATE, parse("Sunday, 6-Nov-94 08:49:37 GMT"));
- }
-
- @Test
- public void testParseWithoutGMT() {
- assertEquals(DATE, parse("Sun Nov 6 08:49:37 1994"));
- }
-
- @Test
- public void testParseWithFunkyTimezone() {
- assertEquals(DATE, parse("Sun Nov 6 08:49:37 1994 -0000"));
- }
-
- @Test
- public void testParseWithSingleDigitHourMinutesAndSecond() {
- assertEquals(DATE, parse("Sunday, 6-Nov-94 8:49:37 GMT"));
- }
-
- @Test
- public void testParseWithSingleDigitTime() {
- assertEquals(DATE, parse("Sunday, 6 Nov 1994 8:49:37 GMT"));
-
- Date _08_09_37 = new Date(TIMESTAMP - 40 * 60 * 1000);
- assertEquals(_08_09_37, parse("Sunday, 6 Nov 1994 8:9:37 GMT"));
- assertEquals(_08_09_37, parse("Sunday, 6 Nov 1994 8:09:37 GMT"));
-
- Date _08_09_07 = new Date(TIMESTAMP - (40 * 60 + 30) * 1000);
- assertEquals(_08_09_07, parse("Sunday, 6 Nov 1994 8:9:7 GMT"));
- assertEquals(_08_09_07, parse("Sunday, 6 Nov 1994 8:9:07 GMT"));
- }
-
- @Test
- public void testParseMidnight() {
- assertEquals(new Date(784080000000L), parse("Sunday, 6 Nov 1994 00:00:00 GMT"));
- }
-
- @Test
- public void testParseInvalidInput() {
- // missing field
- assertNull(parse("Sun, Nov 1994 08:49:37 GMT"));
- assertNull(parse("Sun, 6 1994 08:49:37 GMT"));
- assertNull(parse("Sun, 6 Nov 08:49:37 GMT"));
- assertNull(parse("Sun, 6 Nov 1994 :49:37 GMT"));
- assertNull(parse("Sun, 6 Nov 1994 49:37 GMT"));
- assertNull(parse("Sun, 6 Nov 1994 08::37 GMT"));
- assertNull(parse("Sun, 6 Nov 1994 08:37 GMT"));
- assertNull(parse("Sun, 6 Nov 1994 08:49: GMT"));
- assertNull(parse("Sun, 6 Nov 1994 08:49 GMT"));
- //invalid value
- assertNull(parse("Sun, 6 FOO 1994 08:49:37 GMT"));
- assertNull(parse("Sun, 36 Nov 1994 08:49:37 GMT"));
- assertNull(parse("Sun, 6 Nov 1994 28:49:37 GMT"));
- assertNull(parse("Sun, 6 Nov 1994 08:69:37 GMT"));
- assertNull(parse("Sun, 6 Nov 1994 08:49:67 GMT"));
- //wrong number of digits in timestamp
- assertNull(parse("Sunday, 6 Nov 1994 0:0:000 GMT"));
- assertNull(parse("Sunday, 6 Nov 1994 0:000:0 GMT"));
- assertNull(parse("Sunday, 6 Nov 1994 000:0:0 GMT"));
- }
-
- @Test
- public void testFormat() {
- assertEquals("Sun, 6 Nov 1994 08:49:37 GMT", format(DATE));
- }
-}
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/cookie/ClientCookieDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/cookie/ClientCookieDecoderTest.java
index 5df87de9d0..60b85899c6 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/cookie/ClientCookieDecoderTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/cookie/ClientCookieDecoderTest.java
@@ -15,7 +15,7 @@
*/
package io.netty.handler.codec.http.cookie;
-import io.netty.handler.codec.http.HttpHeaderDateFormatter;
+import io.netty.handler.codec.DateFormatter;
import org.junit.Test;
import java.util.ArrayList;
@@ -30,26 +30,18 @@ import static org.junit.Assert.*;
public class ClientCookieDecoderTest {
@Test
public void testDecodingSingleCookieV0() {
- String cookieString = "myCookie=myValue;expires=XXX;path=/apathsomewhere;domain=.adomainsomewhere;secure;";
- cookieString = cookieString.replace("XXX",
- HttpHeaderDateFormatter.format(new Date(System.currentTimeMillis() + 50000)));
+ String cookieString = "myCookie=myValue;expires="
+ + DateFormatter.format(new Date(System.currentTimeMillis() + 50000))
+ + ";path=/apathsomewhere;domain=.adomainsomewhere;secure;";
Cookie cookie = ClientCookieDecoder.STRICT.decode(cookieString);
assertNotNull(cookie);
assertEquals("myValue", cookie.value());
assertEquals(".adomainsomewhere", cookie.domain());
-
- boolean fail = true;
- for (int i = 40; i <= 60; i++) {
- if (cookie.maxAge() == i) {
- fail = false;
- break;
- }
- }
- if (fail) {
- fail("expected: 50, actual: " + cookie.maxAge());
- }
-
+ assertNotEquals("maxAge should be defined when parsing cookie " + cookieString,
+ Long.MIN_VALUE, cookie.maxAge());
+ assertTrue("maxAge should be about 50ms when parsing cookie " + cookieString,
+ cookie.maxAge() >= 40 && cookie.maxAge() <= 60);
assertEquals("/apathsomewhere", cookie.path());
assertTrue(cookie.isSecure());
}
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/cookie/ServerCookieDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/cookie/ServerCookieDecoderTest.java
index fe9df5ec30..b157bc3c73 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/cookie/ServerCookieDecoderTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/cookie/ServerCookieDecoderTest.java
@@ -17,9 +17,6 @@ package io.netty.handler.codec.http.cookie;
import org.junit.Test;
-import io.netty.handler.codec.http.HttpHeaderDateFormat;
-
-import java.util.Date;
import java.util.Iterator;
import java.util.Set;
@@ -29,9 +26,6 @@ public class ServerCookieDecoderTest {
@Test
public void testDecodingSingleCookie() {
String cookieString = "myCookie=myValue";
- cookieString = cookieString.replace("XXX",
- HttpHeaderDateFormat.get().format(new Date(System.currentTimeMillis() + 50000)));
-
Set cookies = ServerCookieDecoder.STRICT.decode(cookieString);
assertEquals(1, cookies.size());
Cookie cookie = cookies.iterator().next();
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/cookie/ServerCookieEncoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/cookie/ServerCookieEncoderTest.java
index d171679b6c..723a7a17a9 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/cookie/ServerCookieEncoderTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/cookie/ServerCookieEncoderTest.java
@@ -19,7 +19,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import io.netty.handler.codec.http.HttpHeaderDateFormat;
+import io.netty.handler.codec.DateFormatter;
import java.text.ParseException;
import java.util.ArrayList;
@@ -51,7 +51,7 @@ public class ServerCookieEncoderTest {
Matcher matcher = Pattern.compile(result).matcher(encodedCookie);
assertTrue(matcher.find());
- Date expiresDate = HttpHeaderDateFormat.get().parse(matcher.group(1));
+ Date expiresDate = DateFormatter.parseHttpDate(matcher.group(1));
long diff = (expiresDate.getTime() - System.currentTimeMillis()) / 1000;
// 2 secs should be fine
assertTrue(Math.abs(diff - maxAge) <= 2);
diff --git a/codec/src/main/java/io/netty/handler/codec/CharSequenceValueConverter.java b/codec/src/main/java/io/netty/handler/codec/CharSequenceValueConverter.java
index dfdc856c6c..fa833d2c31 100644
--- a/codec/src/main/java/io/netty/handler/codec/CharSequenceValueConverter.java
+++ b/codec/src/main/java/io/netty/handler/codec/CharSequenceValueConverter.java
@@ -14,11 +14,11 @@
*/
package io.netty.handler.codec;
-import io.netty.handler.codec.DefaultHeaders.HeaderDateFormat;
import io.netty.util.AsciiString;
import io.netty.util.internal.PlatformDependent;
import java.text.ParseException;
+import java.util.Date;
/**
* Converts to/from native types, general {@link Object}, and {@link CharSequence}s.
@@ -126,12 +126,12 @@ public class CharSequenceValueConverter implements ValueConverter
@Override
public long convertToTimeMillis(CharSequence value) {
- try {
- return HeaderDateFormat.get().parse(value.toString());
- } catch (ParseException e) {
- PlatformDependent.throwException(e);
+ Date date = DateFormatter.parseHttpDate(value);
+ if (date == null) {
+ PlatformDependent.throwException(new ParseException("header can't be parsed into a Date: " + value, 0));
return 0;
}
+ return date.getTime();
}
@Override
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderDateFormatter.java b/codec/src/main/java/io/netty/handler/codec/DateFormatter.java
similarity index 95%
rename from codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderDateFormatter.java
rename to codec/src/main/java/io/netty/handler/codec/DateFormatter.java
index 729c568cba..0c7e7797dd 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderDateFormatter.java
+++ b/codec/src/main/java/io/netty/handler/codec/DateFormatter.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
-package io.netty.handler.codec.http;
+package io.netty.handler.codec;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
@@ -43,7 +43,7 @@ import java.util.TimeZone;
* @see RFC6265 for the parsing side
* @see RFC1123 for the encoding side.
*/
-public final class HttpHeaderDateFormatter {
+public final class DateFormatter {
private static final BitSet DELIMITERS = new BitSet();
static {
@@ -68,11 +68,11 @@ public final class HttpHeaderDateFormatter {
private static final String[] CALENDAR_MONTH_TO_SHORT_NAME =
new String[]{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
- private static final FastThreadLocal INSTANCES =
- new FastThreadLocal() {
+ private static final FastThreadLocal INSTANCES =
+ new FastThreadLocal() {
@Override
- protected HttpHeaderDateFormatter initialValue() {
- return new HttpHeaderDateFormatter();
+ protected DateFormatter initialValue() {
+ return new DateFormatter();
}
};
@@ -81,8 +81,8 @@ public final class HttpHeaderDateFormatter {
* @param txt text to parse
* @return a {@link Date}, or null if text couldn't be parsed
*/
- public static Date parse(CharSequence txt) {
- return parse(txt, 0, txt.length());
+ public static Date parseHttpDate(CharSequence txt) {
+ return parseHttpDate(txt, 0, txt.length());
}
/**
@@ -92,7 +92,7 @@ public final class HttpHeaderDateFormatter {
* @param end the end index inside txt
* @return a {@link Date}, or null if text couldn't be parsed
*/
- public static Date parse(CharSequence txt, int start, int end) {
+ public static Date parseHttpDate(CharSequence txt, int start, int end) {
int length = end - start;
if (length == 0) {
return null;
@@ -124,8 +124,8 @@ public final class HttpHeaderDateFormatter {
return formatter().append0(checkNotNull(date, "date"), checkNotNull(sb, "sb"));
}
- private static HttpHeaderDateFormatter formatter() {
- HttpHeaderDateFormatter formatter = INSTANCES.get();
+ private static DateFormatter formatter() {
+ DateFormatter formatter = INSTANCES.get();
formatter.reset();
return formatter;
}
@@ -156,7 +156,7 @@ public final class HttpHeaderDateFormatter {
private boolean yearFound;
private int year;
- private HttpHeaderDateFormatter() {
+ private DateFormatter() {
reset();
}
@@ -171,7 +171,7 @@ public final class HttpHeaderDateFormatter {
month = -1;
yearFound = false;
year = -1;
- cal.set(Calendar.MILLISECOND, 0);
+ cal.clear();
sb.setLength(0);
}
diff --git a/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java b/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java
index 5625aec980..a5701f295f 100644
--- a/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java
+++ b/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java
@@ -15,24 +15,17 @@
package io.netty.handler.codec;
import io.netty.util.HashingStrategy;
-import io.netty.util.concurrent.FastThreadLocal;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
-import java.util.TimeZone;
import static io.netty.util.HashingStrategy.JAVA_HASHER;
import static io.netty.util.internal.MathUtil.findNextPositivePowerOfTwo;
@@ -960,77 +953,6 @@ public class DefaultHeaders> implements Headers
return (T) this;
}
- /**
- * This {@link DateFormat} decodes 3 formats of {@link Date}.
- *
- *
- * - Sun, 06 Nov 1994 08:49:37 GMT: standard specification, the only one with valid generation
- * - Sun, 06 Nov 1994 08:49:37 GMT: obsolete specification
- * - Sun Nov 6 08:49:37 1994: obsolete specification
- *
- */
- public static final class HeaderDateFormat {
- private static final FastThreadLocal dateFormatThreadLocal =
- new FastThreadLocal() {
- @Override
- protected HeaderDateFormat initialValue() {
- return new HeaderDateFormat();
- }
- };
-
- static HeaderDateFormat get() {
- return dateFormatThreadLocal.get();
- }
-
- /**
- * Standard date format:
- *
- *
- * Sun, 06 Nov 1994 08:49:37 GMT -> E, d MMM yyyy HH:mm:ss z
- *
- */
- private final DateFormat dateFormat1 = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
-
- /**
- * First obsolete format:
- *
- *
- * Sunday, 06-Nov-94 08:49:37 GMT -> E, d-MMM-y HH:mm:ss z
- *
- */
- private final DateFormat dateFormat2 = new SimpleDateFormat("E, dd-MMM-yy HH:mm:ss z", Locale.ENGLISH);
-
- /**
- * Second obsolete format
- *
- *
- * Sun Nov 6 08:49:37 1994 -> EEE, MMM d HH:mm:ss yyyy
- *
- */
- private final DateFormat dateFormat3 = new SimpleDateFormat("E MMM d HH:mm:ss yyyy", Locale.ENGLISH);
-
- private HeaderDateFormat() {
- TimeZone tz = TimeZone.getTimeZone("GMT");
- dateFormat1.setTimeZone(tz);
- dateFormat2.setTimeZone(tz);
- dateFormat3.setTimeZone(tz);
- }
-
- long parse(String text) throws ParseException {
- Date date = dateFormat1.parse(text);
- if (date == null) {
- date = dateFormat2.parse(text);
- }
- if (date == null) {
- date = dateFormat3.parse(text);
- }
- if (date == null) {
- throw new ParseException(text, 0);
- }
- return date.getTime();
- }
- }
-
private final class HeaderIterator implements Iterator> {
private HeaderEntry current = head;
diff --git a/codec/src/test/java/io/netty/handler/codec/DateFormatterTest.java b/codec/src/test/java/io/netty/handler/codec/DateFormatterTest.java
new file mode 100644
index 0000000000..99d1d3864a
--- /dev/null
+++ b/codec/src/test/java/io/netty/handler/codec/DateFormatterTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2016 The Netty Project
+ *
+ * The Netty Project licenses this file to you 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 io.netty.handler.codec;
+
+import org.junit.Test;
+
+import java.util.Date;
+
+import static org.junit.Assert.*;
+import static io.netty.handler.codec.DateFormatter.*;
+
+public class DateFormatterTest {
+ /**
+ * This date is set at "06 Nov 1994 08:49:37 GMT", from
+ * examples in RFC documentation
+ */
+ private static final long TIMESTAMP = 784111777000L;
+ private static final Date DATE = new Date(TIMESTAMP);
+
+ @Test
+ public void testParseWithSingleDigitDay() {
+ assertEquals(DATE, parseHttpDate("Sun, 6 Nov 1994 08:49:37 GMT"));
+ }
+
+ @Test
+ public void testParseWithDoubleDigitDay() {
+ assertEquals(DATE, parseHttpDate("Sun, 06 Nov 1994 08:49:37 GMT"));
+ }
+
+ @Test
+ public void testParseWithDashSeparatorSingleDigitDay() {
+ assertEquals(DATE, parseHttpDate("Sunday, 06-Nov-94 08:49:37 GMT"));
+ }
+
+ @Test
+ public void testParseWithSingleDoubleDigitDay() {
+ assertEquals(DATE, parseHttpDate("Sunday, 6-Nov-94 08:49:37 GMT"));
+ }
+
+ @Test
+ public void testParseWithoutGMT() {
+ assertEquals(DATE, parseHttpDate("Sun Nov 6 08:49:37 1994"));
+ }
+
+ @Test
+ public void testParseWithFunkyTimezone() {
+ assertEquals(DATE, parseHttpDate("Sun Nov 6 08:49:37 1994 -0000"));
+ }
+
+ @Test
+ public void testParseWithSingleDigitHourMinutesAndSecond() {
+ assertEquals(DATE, parseHttpDate("Sunday, 6-Nov-94 8:49:37 GMT"));
+ }
+
+ @Test
+ public void testParseWithSingleDigitTime() {
+ assertEquals(DATE, parseHttpDate("Sunday, 6 Nov 1994 8:49:37 GMT"));
+
+ Date _08_09_37 = new Date(TIMESTAMP - 40 * 60 * 1000);
+ assertEquals(_08_09_37, parseHttpDate("Sunday, 6 Nov 1994 8:9:37 GMT"));
+ assertEquals(_08_09_37, parseHttpDate("Sunday, 6 Nov 1994 8:09:37 GMT"));
+
+ Date _08_09_07 = new Date(TIMESTAMP - (40 * 60 + 30) * 1000);
+ assertEquals(_08_09_07, parseHttpDate("Sunday, 6 Nov 1994 8:9:7 GMT"));
+ assertEquals(_08_09_07, parseHttpDate("Sunday, 6 Nov 1994 8:9:07 GMT"));
+ }
+
+ @Test
+ public void testParseMidnight() {
+ assertEquals(new Date(784080000000L), parseHttpDate("Sunday, 6 Nov 1994 00:00:00 GMT"));
+ }
+
+ @Test
+ public void testParseInvalidInput() {
+ // missing field
+ assertNull(parseHttpDate("Sun, Nov 1994 08:49:37 GMT"));
+ assertNull(parseHttpDate("Sun, 6 1994 08:49:37 GMT"));
+ assertNull(parseHttpDate("Sun, 6 Nov 08:49:37 GMT"));
+ assertNull(parseHttpDate("Sun, 6 Nov 1994 :49:37 GMT"));
+ assertNull(parseHttpDate("Sun, 6 Nov 1994 49:37 GMT"));
+ assertNull(parseHttpDate("Sun, 6 Nov 1994 08::37 GMT"));
+ assertNull(parseHttpDate("Sun, 6 Nov 1994 08:37 GMT"));
+ assertNull(parseHttpDate("Sun, 6 Nov 1994 08:49: GMT"));
+ assertNull(parseHttpDate("Sun, 6 Nov 1994 08:49 GMT"));
+ //invalid value
+ assertNull(parseHttpDate("Sun, 6 FOO 1994 08:49:37 GMT"));
+ assertNull(parseHttpDate("Sun, 36 Nov 1994 08:49:37 GMT"));
+ assertNull(parseHttpDate("Sun, 6 Nov 1994 28:49:37 GMT"));
+ assertNull(parseHttpDate("Sun, 6 Nov 1994 08:69:37 GMT"));
+ assertNull(parseHttpDate("Sun, 6 Nov 1994 08:49:67 GMT"));
+ //wrong number of digits in timestamp
+ assertNull(parseHttpDate("Sunday, 6 Nov 1994 0:0:000 GMT"));
+ assertNull(parseHttpDate("Sunday, 6 Nov 1994 0:000:0 GMT"));
+ assertNull(parseHttpDate("Sunday, 6 Nov 1994 000:0:0 GMT"));
+ }
+
+ @Test
+ public void testFormat() {
+ assertEquals("Sun, 6 Nov 1994 08:49:37 GMT", format(DATE));
+ }
+}
diff --git a/microbench/src/main/java/io/netty/microbench/http/HttpHeaderDateFormatterBenchmark.java b/microbench/src/main/java/io/netty/handler/codec/DateFormatterBenchmark.java
similarity index 85%
rename from microbench/src/main/java/io/netty/microbench/http/HttpHeaderDateFormatterBenchmark.java
rename to microbench/src/main/java/io/netty/handler/codec/DateFormatterBenchmark.java
index 2c05869a5e..5d2a11adc5 100644
--- a/microbench/src/main/java/io/netty/microbench/http/HttpHeaderDateFormatterBenchmark.java
+++ b/microbench/src/main/java/io/netty/handler/codec/DateFormatterBenchmark.java
@@ -13,10 +13,9 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
-package io.netty.microbench.http;
+package io.netty.handler.codec;
import io.netty.handler.codec.http.HttpHeaderDateFormat;
-import io.netty.handler.codec.http.HttpHeaderDateFormatter;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.OutputTimeUnit;
@@ -24,14 +23,14 @@ import java.util.Date;
import java.util.concurrent.TimeUnit;
@OutputTimeUnit(TimeUnit.SECONDS)
-public class HttpHeaderDateFormatterBenchmark {
+public class DateFormatterBenchmark {
private static final String DATE_STRING = "Sun, 27 Nov 2016 19:18:46 GMT";
private static final Date DATE = new Date(784111777000L);
@Benchmark
public Date parseHttpHeaderDateFormatter() {
- return HttpHeaderDateFormatter.parse(DATE_STRING);
+ return DateFormatter.parseHttpDate(DATE_STRING);
}
@Benchmark
@@ -41,7 +40,7 @@ public class HttpHeaderDateFormatterBenchmark {
@Benchmark
public String formatHttpHeaderDateFormatter() {
- return HttpHeaderDateFormatter.format(DATE);
+ return DateFormatter.format(DATE);
}
@Benchmark