diff --git a/src/main/java/org/jboss/netty/handler/codec/http/CookieDateFormat.java b/src/main/java/org/jboss/netty/handler/codec/http/CookieDateFormat.java deleted file mode 100644 index 1539179c0b..0000000000 --- a/src/main/java/org/jboss/netty/handler/codec/http/CookieDateFormat.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2009 Red Hat, Inc. - * - * Red Hat 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 org.jboss.netty.handler.codec.http; - -import java.text.SimpleDateFormat; -import java.util.Locale; -import java.util.TimeZone; - -/** - * @author The Netty Project - * @author Trustin Lee - * @version $Rev$, $Date$ - */ -final class CookieDateFormat extends SimpleDateFormat { - - private static final long serialVersionUID = 1789486337887402640L; - - CookieDateFormat() { - super("E, d-MMM-y HH:mm:ss z", Locale.ENGLISH); - setTimeZone(TimeZone.getTimeZone("GMT")); - } -} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/CookieDecoder.java b/src/main/java/org/jboss/netty/handler/codec/http/CookieDecoder.java index f1b9ca1e5e..98b5b09fe1 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/CookieDecoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/CookieDecoder.java @@ -134,7 +134,7 @@ public class CookieDecoder { } else if (CookieHeaderNames.EXPIRES.equalsIgnoreCase(name)) { try { long maxAgeMillis = - new CookieDateFormat().parse(value).getTime() - + new HttpHeaderDateFormat().parse(value).getTime() - System.currentTimeMillis(); if (maxAgeMillis <= 0) { maxAge = 0; diff --git a/src/main/java/org/jboss/netty/handler/codec/http/CookieEncoder.java b/src/main/java/org/jboss/netty/handler/codec/http/CookieEncoder.java index 76d94b25bb..c0e551dc47 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/CookieEncoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/CookieEncoder.java @@ -107,7 +107,7 @@ public class CookieEncoder { if (cookie.getMaxAge() >= 0) { if (cookie.getVersion() == 0) { addUnquoted(sb, CookieHeaderNames.EXPIRES, - new CookieDateFormat().format( + new HttpHeaderDateFormat().format( new Date(System.currentTimeMillis() + cookie.getMaxAge() * 1000L))); } else { diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpHeaderDateFormat.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpHeaderDateFormat.java new file mode 100644 index 0000000000..f8bc57b451 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpHeaderDateFormat.java @@ -0,0 +1,91 @@ +/* + * Copyright 2009 Red Hat, Inc. + * + * Red Hat 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 org.jboss.netty.handler.codec.http; + +import java.text.DateFormat; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +/** + * This DateFormat decodes 3 formats of {@link Date}, but only encodes the one, + * the first: + * + * + * @author The Netty Project + * @author Trustin Lee + * @author Rogiel Josias Sulzbach + * @version $Rev$, $Date$ + */ +final class HttpHeaderDateFormat extends SimpleDateFormat { + private static final long serialVersionUID = -925286159755905325L; + + private final SimpleDateFormat format1 = new HttpHeaderDateFormatObsolete1(); + private final SimpleDateFormat format2 = new HttpHeaderDateFormatObsolete2(); + + /** + * Standard date format

+ * Sun, 06 Nov 1994 08:49:37 GMT -> E, d MMM yyyy HH:mm:ss z + */ + HttpHeaderDateFormat() { + super("E, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH); + setTimeZone(TimeZone.getTimeZone("GMT")); + } + + @Override + public Date parse(String text, ParsePosition pos) { + Date date = super.parse(text, pos); + if (date == null) + date = format1.parse(text, pos); + if (date == null) + date = format2.parse(text, pos); + return date; + } + + /** + * First obsolete format

+ * Sunday, 06-Nov-94 08:49:37 GMT -> E, d-MMM-y HH:mm:ss z + */ + private final class HttpHeaderDateFormatObsolete1 extends SimpleDateFormat { + private static final long serialVersionUID = -3178072504225114298L; + + HttpHeaderDateFormatObsolete1() { + super("E, dd-MMM-y HH:mm:ss z", Locale.ENGLISH); + setTimeZone(TimeZone.getTimeZone("GMT")); + } + } + + /** + * Second obsolete format + *

+ * Sun Nov 6 08:49:37 1994 -> EEE, MMM d HH:mm:ss yyyy + */ + private final class HttpHeaderDateFormatObsolete2 extends SimpleDateFormat { + private static final long serialVersionUID = 3010674519968303714L; + + HttpHeaderDateFormatObsolete2() { + super("E MMM d HH:mm:ss yyyy", Locale.ENGLISH); + setTimeZone(TimeZone.getTimeZone("GMT")); + } + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpHeaders.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpHeaders.java index 7fd6d64047..68f747835a 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/HttpHeaders.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpHeaders.java @@ -15,6 +15,8 @@ */ package org.jboss.netty.handler.codec.http; +import java.text.ParseException; +import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -34,6 +36,7 @@ import java.util.TreeSet; * @apiviz.stereotype static */ public class HttpHeaders { + private static final HttpHeaderDateFormat dateFormat = new HttpHeaderDateFormat(); /** * Standard HTTP header names. @@ -686,6 +689,79 @@ public class HttpHeaders { public static void setHost(HttpMessage message, String value) { message.setHeader(Names.HOST, value); } + + + /** + * Returns the value of the {@code "Date"} header. + */ + public static Date getDate(HttpMessage message) { + return getDate(message, null); + } + + /** + * Returns the value of the {@code "Date"} header. If there is no such + * header, the {@code defaultValue} is returned. + */ + public static Date getDate(HttpMessage message, Date defaultValue) { + final String dateString = message.getHeader(Names.DATE); + if (dateString == null) { + return defaultValue; + } + try { + return dateFormat.parse(dateString); + } catch (ParseException e) { + // is that correct? + return defaultValue; + } + } + + /** + * Sets the {@code "Date"} header. + */ + public static void setDate(HttpMessage message, Date value) { + if (value != null) { + message.setHeader(Names.DATE, dateFormat.format(value)); + } else { + message.setHeader(Names.DATE, null); + } + } + + /** + * Returns the value of the {@code "Date"} header. + */ + public static long getDateInMilliseconds(HttpMessage message) { + return getDate(message, null).getTime(); + } + + /** + * Returns the value of the {@code "Date"} header. If there is no such + * header, the {@code defaultValue} is returned. + */ + public static long getDateInMilliseconds(HttpMessage message, + long defaultValue) { + Date date = getDate(message, null); + if (date == null) { + return defaultValue; + } + return date.getTime(); + } + + /** + * Sets the {@code "Date"} header. + * + * @param message + * the {@link HttpMessage} + * @param date + * the date in milliseconds + */ + public static void setDateInMilliseconds(HttpMessage message, long date) { + final Date value = new Date(date); + if (date > 0) { + message.setHeader(Names.DATE, dateFormat.format(value)); + } else { + message.setHeader(Names.DATE, null); + } + } /** * Returns {@code true} if and only if the specified message contains the diff --git a/src/test/java/org/jboss/netty/handler/codec/http/CookieDecoderTest.java b/src/test/java/org/jboss/netty/handler/codec/http/CookieDecoderTest.java index d9e170e909..a0138db92d 100644 --- a/src/test/java/org/jboss/netty/handler/codec/http/CookieDecoderTest.java +++ b/src/test/java/org/jboss/netty/handler/codec/http/CookieDecoderTest.java @@ -15,7 +15,12 @@ */ package org.jboss.netty.handler.codec.http; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.Date; import java.util.Iterator; @@ -33,7 +38,7 @@ public class CookieDecoderTest { @Test public void testDecodingSingleCookieV0() { String cookieString = "myCookie=myValue;expires=XXX;path=/apathsomewhere;domain=.adomainsomewhere;secure;"; - cookieString = cookieString.replace("XXX", new CookieDateFormat().format(new Date(System.currentTimeMillis() + 50000))); + cookieString = cookieString.replace("XXX", new HttpHeaderDateFormat().format(new Date(System.currentTimeMillis() + 50000))); CookieDecoder cookieDecoder = new CookieDecoder(); Set cookies = cookieDecoder.decode(cookieString); diff --git a/src/test/java/org/jboss/netty/handler/codec/http/CookieEncoderTest.java b/src/test/java/org/jboss/netty/handler/codec/http/CookieEncoderTest.java index 0cc97cd78b..889a5fc40e 100644 --- a/src/test/java/org/jboss/netty/handler/codec/http/CookieEncoderTest.java +++ b/src/test/java/org/jboss/netty/handler/codec/http/CookieEncoderTest.java @@ -15,7 +15,8 @@ */ package org.jboss.netty.handler.codec.http; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import java.text.DateFormat; import java.util.Date; @@ -33,7 +34,7 @@ public class CookieEncoderTest { @Test public void testEncodingSingleCookieV0() { String result = "myCookie=myValue;Expires=XXX;Path=/apathsomewhere;Domain=.adomainsomewhere;Secure"; - DateFormat df = new CookieDateFormat(); + DateFormat df = new HttpHeaderDateFormat(); Cookie cookie = new DefaultCookie("myCookie", "myValue"); CookieEncoder encoder = new CookieEncoder(true); encoder.addCookie(cookie); diff --git a/src/test/java/org/jboss/netty/handler/codec/http/HttpHeaderDateFormatTest.java b/src/test/java/org/jboss/netty/handler/codec/http/HttpHeaderDateFormatTest.java new file mode 100644 index 0000000000..471380a8bd --- /dev/null +++ b/src/test/java/org/jboss/netty/handler/codec/http/HttpHeaderDateFormatTest.java @@ -0,0 +1,58 @@ +package org.jboss.netty.handler.codec.http; + +import java.text.ParseException; +import java.util.Date; + +import junit.framework.Assert; + +import org.junit.Test; + +public class HttpHeaderDateFormatTest { + /** + * This date is set at "06 Nov 1994 08:49:37 GMT" (same used in example in + * RFC documentation) + *

+ * http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html + */ + private static final Date DATE = new Date(784111777000L); + + @Test + public void testParse() throws ParseException { + HttpHeaderDateFormat format = new HttpHeaderDateFormat(); + + { + final Date parsed = format.parse("Sun, 6 Nov 1994 08:49:37 GMT"); + Assert.assertNotNull(parsed); + Assert.assertEquals(DATE, parsed); + } + { + final Date parsed = format.parse("Sun, 06 Nov 1994 08:49:37 GMT"); + Assert.assertNotNull(parsed); + Assert.assertEquals(DATE, parsed); + } + { + final Date parsed = format.parse("Sunday, 06-Nov-94 08:49:37 GMT"); + Assert.assertNotNull(parsed); + Assert.assertEquals(DATE, parsed); + } + { + final Date parsed = format.parse("Sunday, 6-Nov-94 08:49:37 GMT"); + Assert.assertNotNull(parsed); + Assert.assertEquals(DATE, parsed); + } + { + final Date parsed = format.parse("Sun Nov 6 08:49:37 1994"); + Assert.assertNotNull(parsed); + Assert.assertEquals(DATE, parsed); + } + } + + @Test + public void testFormat() { + HttpHeaderDateFormat format = new HttpHeaderDateFormat(); + + final String formatted = format.format(DATE); + Assert.assertNotNull(formatted); + Assert.assertEquals("Sun, 06 Nov 1994 08:49:37 GMT", formatted); + } +}