You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by sv...@apache.org on 2017/05/29 14:01:20 UTC

jclouds git commit: JCLOUDS-1295: Support deprecated date formats in the Expires header

Repository: jclouds
Updated Branches:
  refs/heads/master 28c3c33bf -> db2f86bce


JCLOUDS-1295: Support deprecated date formats in the Expires header


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/db2f86bc
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/db2f86bc
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/db2f86bc

Branch: refs/heads/master
Commit: db2f86bcecfe0d68183a166ad07a7f996d332539
Parents: 28c3c33
Author: Ignasi Barrera <na...@apache.org>
Authored: Fri May 26 10:31:50 2017 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Mon May 29 16:59:42 2017 +0300

----------------------------------------------------------------------
 .../java/org/jclouds/date/DateCodecFactory.java |  1 +
 .../internal/DateServiceDateCodecFactory.java   | 34 +++++++++++++
 .../org/jclouds/io/ContentMetadataCodec.java    | 41 +++++++++++++---
 .../DateServiceDateCodecFactoryTest.java        | 19 ++++++++
 .../io/DefaultContentMetadataCodecTest.java     | 51 ++++++++++++++++++++
 5 files changed, 138 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/db2f86bc/core/src/main/java/org/jclouds/date/DateCodecFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/date/DateCodecFactory.java b/core/src/main/java/org/jclouds/date/DateCodecFactory.java
index 19da52f..1fb4ba0 100644
--- a/core/src/main/java/org/jclouds/date/DateCodecFactory.java
+++ b/core/src/main/java/org/jclouds/date/DateCodecFactory.java
@@ -36,4 +36,5 @@ public interface DateCodecFactory {
 
    DateCodec iso8601Seconds();
 
+   DateCodec asctime();
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/db2f86bc/core/src/main/java/org/jclouds/date/internal/DateServiceDateCodecFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/date/internal/DateServiceDateCodecFactory.java b/core/src/main/java/org/jclouds/date/internal/DateServiceDateCodecFactory.java
index b652596..24e443d 100644
--- a/core/src/main/java/org/jclouds/date/internal/DateServiceDateCodecFactory.java
+++ b/core/src/main/java/org/jclouds/date/internal/DateServiceDateCodecFactory.java
@@ -35,6 +35,7 @@ public class DateServiceDateCodecFactory implements DateCodecFactory {
    private final DateCodec rfc1123Codec;
    private final DateCodec iso8601Codec;
    private final DateCodec iso8601SecondsCodec;
+   private final DateCodec asctime;
 
    @Inject
    public DateServiceDateCodecFactory(DateService dateService) {
@@ -43,6 +44,7 @@ public class DateServiceDateCodecFactory implements DateCodecFactory {
       this.rfc1123Codec = new DateServiceRfc1123Codec(dateService);
       this.iso8601Codec = new DateServiceIso8601Codec(dateService);
       this.iso8601SecondsCodec = new DateServiceIso8601SecondsCodec(dateService);
+      this.asctime = new DateServiceAsctimeCodec(dateService);
    }
 
    @Singleton
@@ -153,6 +155,33 @@ public class DateServiceDateCodecFactory implements DateCodecFactory {
 
    }
 
+   @Singleton
+   public static class DateServiceAsctimeCodec implements DateCodec {
+
+      protected final DateService dateService;
+
+      @Inject
+      public DateServiceAsctimeCodec(DateService dateService) {
+         this.dateService = checkNotNull(dateService, "dateService");
+      }
+
+      @Override
+      public Date toDate(String date) throws IllegalArgumentException {
+         return dateService.cDateParse(date);
+      }
+
+      @Override
+      public String toString(Date date) {
+         return dateService.cDateFormat(date);
+      }
+
+      @Override
+      public String toString() {
+         return "asctime()";
+      }
+
+   }
+
    @Override
    public DateCodec rfc822() {
       return rfc822Codec;
@@ -173,4 +202,9 @@ public class DateServiceDateCodecFactory implements DateCodecFactory {
       return iso8601SecondsCodec;
    }
 
+   @Override
+   public DateCodec asctime() {
+      return asctime;
+   }
+   
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/db2f86bc/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java b/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java
index 05de972..242bc5e 100644
--- a/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java
+++ b/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java
@@ -28,6 +28,7 @@ import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
 import static com.google.common.net.HttpHeaders.EXPIRES;
 
 import java.util.Date;
+import java.util.List;
 import java.util.Map.Entry;
 
 import javax.annotation.Resource;
@@ -38,6 +39,7 @@ import org.jclouds.io.ContentMetadataCodec.DefaultContentMetadataCodec;
 import org.jclouds.logging.Logger;
 
 import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.ImmutableMultimap.Builder;
 import com.google.common.collect.Multimap;
@@ -73,16 +75,22 @@ public interface ContentMetadataCodec {
       protected Logger logger = Logger.NULL;
 
       private final DateCodec httpExpiresDateCodec;
+      private final List<DateCodec> httpExpiresDateDecoders;
 
       @Inject
       public DefaultContentMetadataCodec(DateCodecFactory dateCodecs) {
          httpExpiresDateCodec = dateCodecs.rfc1123();
+         httpExpiresDateDecoders = ImmutableList.of(dateCodecs.rfc1123(), dateCodecs.asctime());
       }
-      
+
       protected DateCodec getExpiresDateCodec() {
          return httpExpiresDateCodec;
       }
-      
+
+      protected List<DateCodec> getExpiresDateDecoders() {
+         return httpExpiresDateDecoders;
+      }
+
       @Override
       public Multimap<String, String> toHeaders(ContentMetadata md) {
          Builder<String, String> builder = ImmutableMultimap.builder();
@@ -134,14 +142,31 @@ public interface ContentMetadataCodec {
          }
       }
       
+      /**
+       * Parses the date from the given Expires header.
+       * <p>
+       * According to the RFC, dates should always come in RFC-1123 format.
+       * However, clients should also support older and deprecated formats for
+       * compatibility, so this method will try to parse an RFC-1123 date, and
+       * fallback to the ANSI C format.
+       * 
+       * @see https://tools.ietf.org/html/rfc2616#section-3.3
+       */
       public Date parseExpires(String expires) {
-         try {
-            return (expires != null) ? getExpiresDateCodec().toDate(expires) : null;
-         } catch (IllegalArgumentException e) {
-            logger.debug("Invalid Expires header (%s); should be in RFC-1123 format; treating as already expired: %s",
-                  expires, e.getMessage());
-            return new Date(0);
+         if (expires == null)
+            return null;
+
+         for (DateCodec decoder : getExpiresDateDecoders()) {
+            try {
+               return decoder.toDate(expires);
+            } catch (IllegalArgumentException ex) {
+               logger.trace("Expires header (%s) is not in the expected %s format", expires, decoder);
+               // Continue trying the other decoders
+            }
          }
+
+         logger.debug("Invalid Expires header (%s); should be in RFC-1123 format; treating as already expired", expires);
+         return new Date(0);
       }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/db2f86bc/core/src/test/java/org/jclouds/date/internal/DateServiceDateCodecFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/date/internal/DateServiceDateCodecFactoryTest.java b/core/src/test/java/org/jclouds/date/internal/DateServiceDateCodecFactoryTest.java
index 697925a..4a789f2 100644
--- a/core/src/test/java/org/jclouds/date/internal/DateServiceDateCodecFactoryTest.java
+++ b/core/src/test/java/org/jclouds/date/internal/DateServiceDateCodecFactoryTest.java
@@ -33,6 +33,7 @@ public class DateServiceDateCodecFactoryTest {
    private DateCodec rfc1123Codec;
    private DateCodec iso8601Codec;
    private DateCodec iso8601SecondsCodec;
+   private DateCodec asctimeCodec;
 
    @BeforeTest
    public void setUp() {
@@ -41,6 +42,7 @@ public class DateServiceDateCodecFactoryTest {
       rfc1123Codec = simpleDateCodecFactory.rfc1123();
       iso8601Codec = simpleDateCodecFactory.iso8601();
       iso8601SecondsCodec = simpleDateCodecFactory.iso8601Seconds();
+      asctimeCodec = simpleDateCodecFactory.asctime();
    }
    
    @Test
@@ -110,4 +112,21 @@ public class DateServiceDateCodecFactoryTest {
       } catch (IllegalArgumentException e) {
       }
    }
+   
+   @Test
+   public void testCodecForAsctime() {
+      Date date = new Date(1000);
+      assertEquals(asctimeCodec.toDate(asctimeCodec.toString(date)), date);
+
+      assertEquals(asctimeCodec.toDate("Thu Dec 01 16:00:00 GMT 1994"), new Date(786297600000L));
+   }
+
+   @Test
+   public void testCodecForAsctimeThrowsParseExceptionWhenMalformed() {
+      try {
+         asctimeCodec.toDate("-");
+         fail();
+      } catch (IllegalArgumentException e) {
+      }
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/db2f86bc/core/src/test/java/org/jclouds/io/DefaultContentMetadataCodecTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/io/DefaultContentMetadataCodecTest.java b/core/src/test/java/org/jclouds/io/DefaultContentMetadataCodecTest.java
new file mode 100644
index 0000000..3b18a62
--- /dev/null
+++ b/core/src/test/java/org/jclouds/io/DefaultContentMetadataCodecTest.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.jclouds.io;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Date;
+
+import org.jclouds.date.internal.DateServiceDateCodecFactory;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.io.ContentMetadataCodec.DefaultContentMetadataCodec;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", testName = "DefaultContentMetadataCodecTest")
+public class DefaultContentMetadataCodecTest {
+
+   private final DateServiceDateCodecFactory codecfactory = new DateServiceDateCodecFactory(
+         new SimpleDateFormatDateService());
+
+   public void testCanParseRFC1123Dates() {
+      DefaultContentMetadataCodec codec = new DefaultContentMetadataCodec(codecfactory);
+      Date parsed = codec.parseExpires("Thu, 01 Dec 1994 16:00:00 GMT");
+      assertEquals(parsed, new Date(786297600000L));
+   }
+
+   public void testCanParseAsctimeDates() {
+      DefaultContentMetadataCodec codec = new DefaultContentMetadataCodec(codecfactory);
+      Date parsed = codec.parseExpires("Thu Dec 01 16:00:00 GMT 1994");
+      assertEquals(parsed, new Date(786297600000L));
+   }
+
+   public void testFallbackToExpiredDate() {
+      DefaultContentMetadataCodec codec = new DefaultContentMetadataCodec(codecfactory);
+      Date parsed = codec.parseExpires("1994-12-01T16:00:00.000Z");
+      assertEquals(parsed, new Date(0));
+   }
+}