BUG-4521 Support milliseconds in event-time notification format 64/28764/2
authorMaros Marsalek <mmarsale@cisco.com>
Fri, 23 Oct 2015 22:25:40 +0000 (00:25 +0200)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 5 Nov 2015 14:53:58 +0000 (14:53 +0000)
Current format does not support milliseconds right now and netconf
notification RFC clearly says the milliseconds should be supported

Change-Id: Ib91b5f08a0ec78721e2b0984b8dc123f3283d2e1
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/mapping/NetconfMessageTransformer.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfToNotificationTest.java
opendaylight/md-sal/sal-netconf-connector/src/test/resources/notification-payload.xml
opendaylight/netconf/netconf-notifications-api/src/main/java/org/opendaylight/controller/netconf/notifications/NetconfNotification.java
opendaylight/netconf/netconf-notifications-impl/src/test/java/org/opendaylight/controller/netconf/notifications/impl/NetconfNotificationManagerTest.java

index d580043b20ac61c12d2d112f962ccfb93902e327..e0b9ad688196e4cc45411f34d7be8271f321d3f6 100644 (file)
@@ -145,7 +145,19 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
 
     private static final ThreadLocal<SimpleDateFormat> EVENT_TIME_FORMAT = new ThreadLocal<SimpleDateFormat>() {
         protected SimpleDateFormat initialValue() {
-            return new SimpleDateFormat(NetconfNotification.RFC3339_DATE_FORMAT_BLUEPRINT);
+            final SimpleDateFormat withMillis = new SimpleDateFormat(
+                NetconfNotification.RFC3339_DATE_FORMAT_WITH_MILLIS_BLUEPRINT);
+
+            return new SimpleDateFormat(NetconfNotification.RFC3339_DATE_FORMAT_BLUEPRINT) {
+                @Override public Date parse(final String source) throws ParseException {
+                    try {
+                        return super.parse(source);
+                    } catch (ParseException e) {
+                        // In case of failure, try to parse with milliseconds
+                        return withMillis.parse(source);
+                    }
+                }
+            };
         }
 
         public void set(SimpleDateFormat value) {
@@ -178,7 +190,8 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
         } catch (NetconfDocumentedException e) {
             throw new IllegalArgumentException("Notification payload does not contain " + EVENT_TIME + " " + message);
         } catch (ParseException e) {
-            throw new IllegalArgumentException("Notification event time in wrong format " + EVENT_TIME + " " + message);
+            LOG.warn("Unable to parse event time from {}. Setting time to {}", eventTimeElement, NetconfNotification.UNKNOWN_EVENT_TIME, e);
+            return new AbstractMap.SimpleEntry<>(NetconfNotification.UNKNOWN_EVENT_TIME, notificationElement);
         }
     }
 
index 96c478f0977c2c963ef14c497bd3e64f9c9a0102..dc09cff1d85fa8294b3c4bd2d00afe5f4f2c55f8 100644 (file)
@@ -69,7 +69,7 @@ public class NetconfToNotificationTest {
         assertNotNull(root);
         assertEquals(6, Iterables.size(root.getValue()));
         assertEquals("user-visited-page", root.getNodeType().getLocalName());
-        assertEquals(new SimpleDateFormat(NetconfNotification.RFC3339_DATE_FORMAT_BLUEPRINT).parse("2007-07-08T00:01:00Z"),
+        assertEquals(new SimpleDateFormat(NetconfNotification.RFC3339_DATE_FORMAT_WITH_MILLIS_BLUEPRINT).parse("2015-10-23T09:42:27.67175+00:00"),
                 ((DOMEvent) domNotification).getEventTime());
     }
 }
index 431787d34c929b84d56e98a675f4228010a64bed..e7d551378a2a8fcc42a735c2aba10605a0ec2758 100644 (file)
@@ -1,5 +1,5 @@
 <notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
-<eventTime>2007-07-08T00:01:00Z</eventTime>
+<eventTime>2015-10-23T09:42:27.67175+00:00</eventTime>
 <user-visited-page xmlns="org:opendaylight:notification:test:ns:yang:user-notification">
   <ui:incoming-user xmlns:ui="org:opendaylight:notification:test:ns:yang:user-notification">ui:public-user</ui:incoming-user>
   <ip-address>172.23.29.104</ip-address>
index efa42c03e99d2deacba2c48e5657d3a71ab68ccc..d9a9e1d685c800aad9a3a7861f89a0e24df3145e 100644 (file)
@@ -23,8 +23,17 @@ public final class NetconfNotification extends NetconfMessage {
     public static final String NOTIFICATION = "notification";
     public static final String NOTIFICATION_NAMESPACE = "urn:ietf:params:netconf:capability:notification:1.0";
     public static final String RFC3339_DATE_FORMAT_BLUEPRINT = "yyyy-MM-dd'T'HH:mm:ssXXX";
+    // The format with milliseconds is a bit fragile, it cannot be used for timestamps without millis (thats why its a separate format)
+    // + it might not work properly with more than 6 digits
+    // TODO try to find a better solution with Java8
+    public static final String RFC3339_DATE_FORMAT_WITH_MILLIS_BLUEPRINT = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX";
     public static final String EVENT_TIME = "eventTime";
 
+    /**
+     * Used for unknown/un-parse-able event-times
+     */
+    public static final Date UNKNOWN_EVENT_TIME = new Date(0);
+
     /**
      * Create new notification and capture the timestamp in the constructor
      */
index 36d2015ab720595dd3ee6317f6a8f9bcbe4eb1e4..34a9cbfa2bcc3fa42c7d48c03c7c24d4749c7b2e 100644 (file)
@@ -15,6 +15,9 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import com.google.common.collect.Lists;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
@@ -40,6 +43,25 @@ public class NetconfNotificationManagerTest {
         MockitoAnnotations.initMocks(this);
     }
 
+    @Test public void testEventTime() throws Exception {
+        final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
+            NetconfNotification.RFC3339_DATE_FORMAT_BLUEPRINT);
+        final SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat(
+            NetconfNotification.RFC3339_DATE_FORMAT_WITH_MILLIS_BLUEPRINT);
+
+        for (String time : Lists.newArrayList("2001-07-04T12:08:56.235-07:00", "2015-10-23T09:42:27.67175+00:00",
+            "1970-01-01T17:17:22.229568+00:00", "1937-01-01T12:00:27.87+00:20", "1990-12-31T15:59:60-08:00",
+            "1990-12-31T23:59:60Z", "1996-12-19T16:39:57-08:00"
+            //          ,"1985-04-12T23:20:50.52Z"
+        )) {
+            try {
+                simpleDateFormat.parse(time);
+            } catch (ParseException e) {
+                simpleDateFormat2.parse(time);
+            }
+        }
+    }
+
     @Test
     public void testNotificationListeners() throws Exception {
         final NetconfNotificationManager netconfNotificationManager = new NetconfNotificationManager();