Author: awiner
Date: Mon Mar 16 18:55:29 2009
New Revision: 754978
URL: http://svn.apache.org/viewvc?rev=754978&view=rev
Log:
SHINDIG-933: JsonSerializer doesn't serialize dates as valid xs:date or
xs:dateTime
- Patch from Aaron Evans, slightly cleaned up (use Joda ISODateTimeFormat class)
- Added Javascript ISO parsing routine to create Date objects off of ISO strings
Modified:
incubator/shindig/trunk/features/pom.xml
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-base/fieldtranslations.js
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-base/jsonperson.js
incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/JsonSerializer.java
incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/util/DateUtil.java
incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/common/util/DateUtilTest.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponse.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseTest.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpServletResponseRecorder.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ServletTestFixture.java
Modified: incubator/shindig/trunk/features/pom.xml
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/pom.xml?rev=754978&r1=754977&r2=754978&view=diff
==============================================================================
--- incubator/shindig/trunk/features/pom.xml (original)
+++ incubator/shindig/trunk/features/pom.xml Mon Mar 16 18:55:29 2009
@@ -102,6 +102,7 @@
<source>opensocial-reference/phone.js</source>
<source>opensocial-reference/responseitem.js</source>
<source>opensocial-reference/url.js</source>
+ <source>opensocial-base/fieldtranslations.js</source>
<source>opensocial-base/jsonactivity.js</source>
<source>opensocial-base/jsonperson.js</source>
<source>opensocial-rest/restfulcontainer.js</source>
Modified:
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-base/fieldtranslations.js
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/main/javascript/features/opensocial-base/fieldtranslations.js?rev=754978&r1=754977&r2=754978&view=diff
==============================================================================
---
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-base/fieldtranslations.js
(original)
+++
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-base/fieldtranslations.js
Mon Mar 16 18:55:29 2009
@@ -114,7 +114,33 @@
}
// displayName and id always need to be requested
- fields.push("id");
- fields.push("displayName");
+ fields.push('id');
+ fields.push('displayName');
};
+FieldTranslations.translateIsoStringToDate = function(isoString) {
+ // Date parsing code from http://delete.me.uk/2005/03/iso8601.html
+ var regexp = '([0-9]{4})(-([0-9]{2})(-([0-9]{2})' +
+ '(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?' +
+ '(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?';
+ var d = isoString.match(new RegExp(regexp));
+
+ var offset = 0;
+ var date = new Date(d[1], 0, 1);
+
+ if (d[3]) { date.setMonth(d[3] - 1); }
+ if (d[5]) { date.setDate(d[5]); }
+ if (d[7]) { date.setHours(d[7]); }
+ if (d[8]) { date.setMinutes(d[8]); }
+ if (d[10]) { date.setSeconds(d[10]); }
+ if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
+ if (d[14]) {
+ offset = (Number(d[16]) * 60) + Number(d[17]);
+ offset *= ((d[15] == '-') ? 1 : -1);
+ }
+
+ offset -= date.getTimezoneOffset();
+ time = (Number(date) + (offset * 60 * 1000));
+
+ return new Date(Number(time));
+}
\ No newline at end of file
Modified:
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-base/jsonperson.js
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/main/javascript/features/opensocial-base/jsonperson.js?rev=754978&r1=754977&r2=754978&view=diff
==============================================================================
---
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-base/jsonperson.js
(original)
+++
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-base/jsonperson.js
Mon Mar 16 18:55:29 2009
@@ -28,11 +28,12 @@
JsonPerson.constructObject(opt_params, "bodyType", opensocial.BodyType);
JsonPerson.constructObject(opt_params, "currentLocation",
opensocial.Address);
- JsonPerson.constructObject(opt_params, "dateOfBirth", Date);
JsonPerson.constructObject(opt_params, "name", opensocial.Name);
JsonPerson.constructObject(opt_params, "profileSong", opensocial.Url);
JsonPerson.constructObject(opt_params, "profileVideo", opensocial.Url);
+ JsonPerson.constructDate(opt_params, "dateOfBirth");
+
JsonPerson.constructArrayObject(opt_params, "addresses", opensocial.Address);
JsonPerson.constructArrayObject(opt_params, "emails", opensocial.Email);
JsonPerson.constructArrayObject(opt_params, "jobs", opensocial.Organization);
@@ -78,6 +79,14 @@
}
};
+// Converts the fieldName into an instance of a Date
+JsonPerson.constructDate = function(map, fieldName) {
+ var fieldValue = map[fieldName];
+ if (fieldValue) {
+ map[fieldName] = FieldTranslations.translateIsoStringToDate(fieldValue);
+ }
+};
+
JsonPerson.constructArrayObject = function(map, fieldName, className) {
var fieldValue = map[fieldName];
if (fieldValue) {
Modified:
incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/JsonSerializer.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/JsonSerializer.java?rev=754978&r1=754977&r2=754978&view=diff
==============================================================================
---
incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/JsonSerializer.java
(original)
+++
incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/JsonSerializer.java
Mon Mar 16 18:55:29 2009
@@ -22,6 +22,7 @@
import com.google.common.collect.Maps;
import com.google.common.collect.MapMaker;
+import org.apache.shindig.common.util.DateUtil;
import org.joda.time.DateTime;
import org.json.JSONArray;
import org.json.JSONObject;
@@ -157,10 +158,11 @@
buf.append(value.toString());
} else if (value instanceof CharSequence ||
value instanceof DateTime ||
- value instanceof Date ||
value.getClass().isEnum()) {
// String-like Primitives
appendString(buf, value.toString());
+ } else if(value instanceof Date) {
+ appendString(buf, DateUtil.formatIso8601Date((Date)value));
} else if (value instanceof JSONObject) {
appendJsonObject(buf, (JSONObject) value);
} else if (value instanceof JSONArray) {
Modified:
incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/util/DateUtil.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/util/DateUtil.java?rev=754978&r1=754977&r2=754978&view=diff
==============================================================================
---
incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/util/DateUtil.java
(original)
+++
incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/util/DateUtil.java
Mon Mar 16 18:55:29 2009
@@ -18,9 +18,11 @@
*/
package org.apache.shindig.common.util;
+import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.ISODateTimeFormat;
import java.util.Date;
import java.util.Locale;
@@ -29,12 +31,15 @@
* Date parsing and writing utilities.
*/
public class DateUtil {
-
+
private static final DateTimeFormatter rfc1123DateFormat = DateTimeFormat
.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'")
.withLocale(Locale.US)
.withZone(DateTimeZone.UTC);
+ private static final DateTimeFormatter iso8601DateFormat =
ISODateTimeFormat.dateTime()
+ .withZone(DateTimeZone.UTC);
+
private DateUtil() {}
/**
@@ -44,7 +49,7 @@
* @param dateStr
* @return the date
*/
- public static Date parseDate(String dateStr) {
+ public static Date parseRfc1123Date(String dateStr) {
try {
return rfc1123DateFormat.parseDateTime(dateStr).toDate();
} catch (Exception e) {
@@ -52,18 +57,49 @@
return null;
}
}
+
+ /**
+ * Parses an ISO8601 formatted datetime into a Date or null
+ * is parsing fails.
+ *
+ * @param dateStr A datetime string in ISO8601 format
+ * @return the date
+ */
+ public static Date parseIso8601DateTime(String dateStr) {
+ try {
+ // joda does our ISO 8601 parsing
+ return new DateTime(dateStr).toDate();
+ } catch(Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Formats an ISO 8601 format date.
+ */
+ public static String formatIso8601Date(Date date) {
+ return formatIso8601Date(date.getTime());
+ }
+
+ /**
+ * Formats an ISO 8601 format date.
+ */
+ public static String formatIso8601Date(long time) {
+ return iso8601DateFormat.print(time);
+ }
/**
* Formats an RFC 1123 format date.
*/
- public static String formatDate(Date date) {
- return formatDate(date.getTime());
+ public static String formatRfc1123Date(Date date) {
+ return formatRfc1123Date(date.getTime());
}
/**
* Formats an RFC 1123 format date.
*/
- public static String formatDate(long timeStamp) {
+ public static String formatRfc1123Date(long timeStamp) {
return rfc1123DateFormat.print(timeStamp);
}
+
}
Modified:
incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/common/util/DateUtilTest.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/common/util/DateUtilTest.java?rev=754978&r1=754977&r2=754978&view=diff
==============================================================================
---
incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/common/util/DateUtilTest.java
(original)
+++
incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/common/util/DateUtilTest.java
Mon Mar 16 18:55:29 2009
@@ -28,14 +28,21 @@
public class DateUtilTest {
- String[] text = {
+ String[] rfc1123text = new String[] {
"Tue, 27 May 2008 05:12:50 GMT",
"Wed, 28 May 2008 04:40:48 GMT",
"Mon, 30 Jun 3090 03:29:55 GMT",
"Fri, 06 Jun 1670 01:57:27 GMT",
};
- Date[] timeStamps = {
+ String[] iso8601text = new String[] {
+ "2008-05-27T05:12:50.000Z",
+ "2008-05-28T04:40:48.000Z",
+ "3090-06-30T03:29:55.000Z",
+ "1670-06-06T01:57:27.000Z"
+ };
+
+ Date[] timeStamps = new Date[] {
new Date(1211865170000L),
new Date(1211949648000L),
new Date(35359385395000L),
@@ -44,48 +51,67 @@
@Test
public void parse() {
- for (int i = 0, j = text.length; i < j; ++i) {
- assertEquals(timeStamps[i].getTime(),
DateUtil.parseDate(text[i]).getTime());
- }
+ for (int i = 0, j = rfc1123text.length; i < j; ++i) {
+ assertEquals(timeStamps[i].getTime(),
DateUtil.parseRfc1123Date(rfc1123text[i]).getTime());
+ }
}
@Test
public void format() {
for (int i = 0, j = timeStamps.length; i < j; ++i) {
- assertEquals(text[i], DateUtil.formatDate(timeStamps[i].getTime()));
+ assertEquals(rfc1123text[i],
DateUtil.formatRfc1123Date(timeStamps[i].getTime()));
}
}
-
+
@Test
- public void formatDate() {
+ public void formatIso8601() {
+ for (int i = 0, j = timeStamps.length; i < j; ++i) {
+ assertEquals(iso8601text[i],
DateUtil.formatIso8601Date(timeStamps[i].getTime()));
+ }
+ }
+
+ @Test
+ public void formatRfc1123Date() {
for (int i = 0, j = timeStamps.length; i < j; ++i) {
- assertEquals(text[i], DateUtil.formatDate(timeStamps[i]));
+ assertEquals(rfc1123text[i], DateUtil.formatRfc1123Date(timeStamps[i]));
}
}
-
+
@Test
- public void parseMalformed() {
- assertNull(DateUtil.parseDate("Invalid date format"));
+ public void formatIso8601Date() {
+ for (int i = 0, j = timeStamps.length; i < j; ++i) {
+ assertEquals(iso8601text[i],
DateUtil.formatIso8601Date(timeStamps[i]));
+ }
}
-
+
+ @Test
+ public void parseMalformedRfc1123() {
+ assertNull(DateUtil.parseRfc1123Date("Invalid date format"));
+ }
+
+ @Test
+ public void parseMalformedIso8691() {
+ assertNull(DateUtil.parseIso8601DateTime("invalid date format"));
+ }
+
@Test
public void parseWrongTimeZone() {
String expires = "Mon, 12 May 2008 09:23:29 PDT";
- assertNull(DateUtil.parseDate(expires));
+ assertNull(DateUtil.parseRfc1123Date(expires));
}
@Test
public void parseRfc1036() {
// We don't support this, though RFC 2616 suggests we should
String expires = "Sunday, 06-Nov-94 08:49:37 GMT";
- assertNull(DateUtil.parseDate(expires));
+ assertNull(DateUtil.parseRfc1123Date(expires));
}
@Test
public void parseAsctime() {
// We don't support this, though RFC 2616 suggests we should
String expires = "Sun Nov 6 08:49:37 1994";
- assertNull(DateUtil.parseDate(expires));
+ assertNull(DateUtil.parseRfc1123Date(expires));
}
@Test
@@ -93,7 +119,7 @@
Locale orig = Locale.getDefault();
try {
Locale.setDefault(Locale.ITALY);
- formatDate();
+ formatRfc1123Date();
} finally {
Locale.setDefault(orig);
}
Modified:
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponse.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponse.java?rev=754978&r1=754977&r2=754978&view=diff
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponse.java
(original)
+++
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponse.java
Mon Mar 16 18:55:29 2009
@@ -363,7 +363,7 @@
private long getExpiresTime() {
String expires = getHeader("Expires");
if (expires != null) {
- Date expiresDate = DateUtil.parseDate(expires);
+ Date expiresDate = DateUtil.parseRfc1123Date(expires);
if (expiresDate != null) {
return expiresDate.getTime();
}
@@ -406,14 +406,14 @@
Collection<String> dates = headers.get("Date");
if (!dates.isEmpty()) {
- Date d = DateUtil.parseDate(dates.iterator().next());
+ Date d = DateUtil.parseRfc1123Date(dates.iterator().next());
if (d != null) {
timestamp = d.getTime();
}
}
if (timestamp == -1) {
timestamp = System.currentTimeMillis();
- headers.put("Date", DateUtil.formatDate(timestamp));
+ headers.put("Date", DateUtil.formatRfc1123Date(timestamp));
}
return timestamp;
}
Modified:
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java?rev=754978&r1=754977&r2=754978&view=diff
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java
(original)
+++
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java
Mon Mar 16 18:55:29 2009
@@ -160,7 +160,7 @@
public HttpResponseBuilder setExpirationTime(long expirationTime) {
headers.removeAll("Cache-Control");
headers.removeAll("Pragma");
- headers.put("Expires", DateUtil.formatDate(expirationTime));
+ headers.put("Expires", DateUtil.formatRfc1123Date(expirationTime));
return this;
}
Modified:
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseTest.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseTest.java?rev=754978&r1=754977&r2=754978&view=diff
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseTest.java
(original)
+++
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseTest.java
Mon Mar 16 18:55:29 2009
@@ -246,7 +246,7 @@
int maxAge = 10;
int time = roundToSeconds(System.currentTimeMillis()) + maxAge;
HttpResponse response = new HttpResponseBuilder()
- .addHeader("Expires", DateUtil.formatDate(1000L * time))
+ .addHeader("Expires", DateUtil.formatRfc1123Date(1000L * time))
.create();
assertEquals(time, roundToSeconds(response.getCacheExpiration()));
// Second rounding makes this n-1.
@@ -288,7 +288,7 @@
int maxAge = 10;
int now = roundToSeconds(System.currentTimeMillis());
HttpResponse response = new HttpResponseBuilder()
- .addHeader("Date", DateUtil.formatDate(1000L * now))
+ .addHeader("Date", DateUtil.formatRfc1123Date(1000L * now))
.addHeader("Cache-Control", "public, max-age=" + maxAge)
.create();
@@ -300,7 +300,7 @@
public void testFixedDate() throws Exception {
int time = roundToSeconds(System.currentTimeMillis());
HttpResponse response = new HttpResponseBuilder()
- .addHeader("Date", DateUtil.formatDate(1000L * time))
+ .addHeader("Date", DateUtil.formatRfc1123Date(1000L * time))
.create();
assertEquals(time + roundToSeconds(HttpResponse.DEFAULT_TTL),
roundToSeconds(response.getCacheExpiration()));
@@ -352,7 +352,7 @@
public void testSetNoCache() {
int time = roundToSeconds(System.currentTimeMillis());
HttpResponse response = new HttpResponseBuilder()
- .addHeader("Expires", DateUtil.formatDate(1000L * time))
+ .addHeader("Expires", DateUtil.formatRfc1123Date(1000L * time))
.setStrictNoCache()
.create();
assertNull(response.getHeader("Expires"));
@@ -423,7 +423,7 @@
.addHeader("Foo", "bar")
.addHeader("Foo", "baz")
.addHeader("Blah", "blah")
- .addHeader("Date", DateUtil.formatDate(now))
+ .addHeader("Date", DateUtil.formatRfc1123Date(now))
.setHttpStatusCode(204)
.setResponseString("This is the response string")
.setMetadata("foo", "bar")
@@ -440,7 +440,7 @@
.addHeader("Foo", "bar")
.addHeader("Foo", "baz")
.addHeader("Blah", "blah")
- .addHeader("Date", DateUtil.formatDate(now))
+ .addHeader("Date", DateUtil.formatRfc1123Date(now))
.setHttpStatusCode(204)
.setResponseString("This is the response string")
.create();
Modified:
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpServletResponseRecorder.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpServletResponseRecorder.java?rev=754978&r1=754977&r2=754978&view=diff
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpServletResponseRecorder.java
(original)
+++
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/HttpServletResponseRecorder.java
Mon Mar 16 18:55:29 2009
@@ -100,7 +100,7 @@
@Override
public void addDateHeader(String name, long date) {
- headers.put(name, DateUtil.formatDate(date));
+ headers.put(name, DateUtil.formatRfc1123Date(date));
}
@Override
Modified:
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ServletTestFixture.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ServletTestFixture.java?rev=754978&r1=754977&r2=754978&view=diff
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ServletTestFixture.java
(original)
+++
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ServletTestFixture.java
Mon Mar 16 18:55:29 2009
@@ -64,7 +64,7 @@
public void checkCacheControlHeaders(int ttl, boolean noProxy) {
- long expires = DateUtil.parseDate(recorder.getHeader("Expires")).getTime();
+ long expires =
DateUtil.parseRfc1123Date(recorder.getHeader("Expires")).getTime();
long lowerBound = testStartTime + (1000L * (ttl - 1));
long upperBound = lowerBound + 2000L;