mirror of https://github.com/apache/jclouds.git
Modified DateService to be explicit about date formats, and to use SimpleDateFormat when it's faster. Also modified test to better check thread safety and provide *unreliable* performance feedback
git-svn-id: http://jclouds.googlecode.com/svn/trunk@826 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
60c25b0a8d
commit
c6adc326bc
|
@ -110,7 +110,7 @@ public class ParseMetadataFromHeaders extends
|
||||||
String lastModified = getResponse().getFirstHeaderOrNull(
|
String lastModified = getResponse().getFirstHeaderOrNull(
|
||||||
HttpHeaders.LAST_MODIFIED);
|
HttpHeaders.LAST_MODIFIED);
|
||||||
metadata.setLastModified(dateParser
|
metadata.setLastModified(dateParser
|
||||||
.dateTimeFromHeaderFormat(lastModified));
|
.rfc822DateParse(lastModified));
|
||||||
if (metadata.getLastModified() == null)
|
if (metadata.getLastModified() == null)
|
||||||
throw new HttpException("could not parse: "
|
throw new HttpException("could not parse: "
|
||||||
+ HttpHeaders.LAST_MODIFIED + ": " + lastModified);
|
+ HttpHeaders.LAST_MODIFIED + ": " + lastModified);
|
||||||
|
|
|
@ -179,7 +179,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
||||||
checkState(getIfUnmodifiedSince() == null,
|
checkState(getIfUnmodifiedSince() == null,
|
||||||
"ifUnmodifiedSince() is not compatible with ifModifiedSince()");
|
"ifUnmodifiedSince() is not compatible with ifModifiedSince()");
|
||||||
replaceHeader("x-amz-copy-source-if-modified-since",
|
replaceHeader("x-amz-copy-source-if-modified-since",
|
||||||
dateService.toHeaderString(checkNotNull(ifModifiedSince,
|
dateService.rfc822DateFormat(checkNotNull(ifModifiedSince,
|
||||||
"ifModifiedSince")));
|
"ifModifiedSince")));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -196,7 +196,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
||||||
checkState(getIfModifiedSince() == null,
|
checkState(getIfModifiedSince() == null,
|
||||||
"ifModifiedSince() is not compatible with ifUnmodifiedSince()");
|
"ifModifiedSince() is not compatible with ifUnmodifiedSince()");
|
||||||
replaceHeader("x-amz-copy-source-if-unmodified-since", dateService
|
replaceHeader("x-amz-copy-source-if-unmodified-since", dateService
|
||||||
.toHeaderString(checkNotNull(ifUnmodifiedSince,
|
.rfc822DateFormat(checkNotNull(ifUnmodifiedSince,
|
||||||
"ifUnmodifiedSince")));
|
"ifUnmodifiedSince")));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
|
||||||
checkArgument(getIfUnmodifiedSince() == null,
|
checkArgument(getIfUnmodifiedSince() == null,
|
||||||
"ifUnmodifiedSince() is not compatible with ifModifiedSince()");
|
"ifUnmodifiedSince() is not compatible with ifModifiedSince()");
|
||||||
this.headers.put(HttpHeaders.IF_MODIFIED_SINCE,
|
this.headers.put(HttpHeaders.IF_MODIFIED_SINCE,
|
||||||
dateService.toHeaderString(checkNotNull(ifModifiedSince,
|
dateService.rfc822DateFormat(checkNotNull(ifModifiedSince,
|
||||||
"ifModifiedSince")));
|
"ifModifiedSince")));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
|
||||||
checkArgument(getIfModifiedSince() == null,
|
checkArgument(getIfModifiedSince() == null,
|
||||||
"ifModifiedSince() is not compatible with ifUnmodifiedSince()");
|
"ifModifiedSince() is not compatible with ifUnmodifiedSince()");
|
||||||
this.headers.put(HttpHeaders.IF_UNMODIFIED_SINCE, dateService
|
this.headers.put(HttpHeaders.IF_UNMODIFIED_SINCE, dateService
|
||||||
.toHeaderString(checkNotNull(ifUnmodifiedSince,
|
.rfc822DateFormat(checkNotNull(ifUnmodifiedSince,
|
||||||
"ifUnmodifiedSince")));
|
"ifUnmodifiedSince")));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter {
|
||||||
// amazon is ok with up to 15 minutes off their time, so let's
|
// amazon is ok with up to 15 minutes off their time, so let's
|
||||||
// be as lazy as possible.
|
// be as lazy as possible.
|
||||||
String createNewStamp() {
|
String createNewStamp() {
|
||||||
return dateService.timestampAsHeaderString();
|
return dateService.rfc822DateFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String timestampAsHeaderString() {
|
public String timestampAsHeaderString() {
|
||||||
|
|
|
@ -23,35 +23,103 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.aws.s3.util;
|
package org.jclouds.aws.s3.util;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.SimpleTimeZone;
|
||||||
|
|
||||||
|
import net.jcip.annotations.GuardedBy;
|
||||||
|
import net.jcip.annotations.ThreadSafe;
|
||||||
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
import org.joda.time.format.DateTimeFormat;
|
import org.joda.time.format.DateTimeFormat;
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses dates found in XML responses and HTTP response headers.
|
* Parses and formats the ISO8601 and RFC822 date formats found in
|
||||||
|
* XML responses and HTTP response headers.
|
||||||
|
* <p>
|
||||||
|
* Either {@link SimpleDateFormat} or {@link DateTimeFormatter}
|
||||||
|
* classes are used internally, depending on which version gives
|
||||||
|
* the best performance.
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*
|
* @author James Murty
|
||||||
*/
|
*/
|
||||||
public class DateService {
|
@ThreadSafe
|
||||||
private DateTimeFormatter headerDateFormat = DateTimeFormat
|
public class DateService {
|
||||||
.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'");
|
/*
|
||||||
|
* Use default Java Date/SimpleDateFormat classes for date
|
||||||
|
* manipulation, but be *very* careful to guard against
|
||||||
|
* the lack of thread safety.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@GuardedBy("this")
|
||||||
|
private static final SimpleDateFormat iso8601SimpleDateFormat =
|
||||||
|
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
|
||||||
|
|
||||||
public DateTime dateTimeFromXMLFormat(String toParse) {
|
@GuardedBy("this")
|
||||||
// the format is natively parseable from the DateTime constructor
|
private static final SimpleDateFormat rfc822SimpleDateFormat =
|
||||||
return new DateTime(toParse);
|
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
|
||||||
|
|
||||||
|
private static final DateTimeFormatter iso8601DateTimeFormatter =
|
||||||
|
DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
|
||||||
|
.withLocale(Locale.US).withZone(DateTimeZone.forID("GMT"));
|
||||||
|
|
||||||
|
private static final DateTimeFormatter rfc822DateTimeFormatter =
|
||||||
|
DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'")
|
||||||
|
.withLocale(Locale.US).withZone(DateTimeZone.forID("GMT"));
|
||||||
|
|
||||||
|
static {
|
||||||
|
iso8601SimpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
|
||||||
|
rfc822SimpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public final String rfc822DateFormat(DateTime dateTime) {
|
||||||
|
return rfc822DateTimeFormatter.print(dateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DateTime dateTimeFromHeaderFormat(String toParse) {
|
public final String rfc822DateFormat(Date date) {
|
||||||
return headerDateFormat.parseDateTime(toParse);
|
return rfc822DateFormat(new DateTime(date));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String timestampAsHeaderString() {
|
public final String rfc822DateFormat() {
|
||||||
return toHeaderString(new DateTime());
|
return rfc822DateFormat(new DateTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
public final DateTime rfc822DateParse(String toParse) {
|
||||||
|
synchronized (rfc822SimpleDateFormat) {
|
||||||
|
try {
|
||||||
|
return new DateTime(rfc822SimpleDateFormat.parse(toParse));
|
||||||
|
} catch (ParseException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toHeaderString(DateTime date) {
|
public final String iso8601DateFormat(DateTime dateTime) {
|
||||||
return headerDateFormat.print(date.withZone(DateTimeZone.UTC));
|
return iso8601DateTimeFormatter.print(dateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final String iso8601DateFormat(Date date) {
|
||||||
|
return iso8601DateFormat(new DateTime(date));
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String iso8601DateFormat() {
|
||||||
|
return iso8601DateFormat(new DateTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
public final DateTime iso8601DateParse(String toParse) {
|
||||||
|
synchronized (iso8601SimpleDateFormat) {
|
||||||
|
try {
|
||||||
|
return new DateTime(iso8601SimpleDateFormat.parse(toParse));
|
||||||
|
} catch (ParseException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class CopyObjectHandler extends
|
||||||
.replaceAll("\"", "")));
|
.replaceAll("\"", "")));
|
||||||
} else if (qName.equals("LastModified")) {
|
} else if (qName.equals("LastModified")) {
|
||||||
metadata.setLastModified(dateParser
|
metadata.setLastModified(dateParser
|
||||||
.dateTimeFromXMLFormat(currentText.toString()));
|
.iso8601DateParse(currentText.toString()));
|
||||||
}
|
}
|
||||||
currentText = new StringBuilder();
|
currentText = new StringBuilder();
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class ListAllMyBucketsHandler extends
|
||||||
currentS3Bucket = new S3Bucket.Metadata(currentText.toString());
|
currentS3Bucket = new S3Bucket.Metadata(currentText.toString());
|
||||||
} else if (qName.equals("CreationDate")) {
|
} else if (qName.equals("CreationDate")) {
|
||||||
currentS3Bucket.setCreationDate(dateParser
|
currentS3Bucket.setCreationDate(dateParser
|
||||||
.dateTimeFromXMLFormat(currentText.toString()));
|
.iso8601DateParse(currentText.toString()));
|
||||||
}
|
}
|
||||||
currentText = new StringBuilder();
|
currentText = new StringBuilder();
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<S3Bucket> {
|
||||||
.toString());
|
.toString());
|
||||||
} else if (qName.equals("LastModified")) {
|
} else if (qName.equals("LastModified")) {
|
||||||
currentObjectMetadata.setLastModified(dateParser
|
currentObjectMetadata.setLastModified(dateParser
|
||||||
.dateTimeFromXMLFormat(currentText.toString()));
|
.iso8601DateParse(currentText.toString()));
|
||||||
} else if (qName.equals("ETag")) {
|
} else if (qName.equals("ETag")) {
|
||||||
currentObjectMetadata.setMd5(S3Utils.fromHexString(currentText
|
currentObjectMetadata.setMd5(S3Utils.fromHexString(currentText
|
||||||
.toString().replaceAll("\"", "")));
|
.toString().replaceAll("\"", "")));
|
||||||
|
|
|
@ -348,13 +348,13 @@ public class StubS3Connection implements S3Connection {
|
||||||
throwResponseException(412);
|
throwResponseException(412);
|
||||||
}
|
}
|
||||||
if (options.getIfModifiedSince() != null) {
|
if (options.getIfModifiedSince() != null) {
|
||||||
DateTime modifiedSince = dateService.dateTimeFromHeaderFormat(options.getIfModifiedSince());
|
DateTime modifiedSince = dateService.rfc822DateParse(options.getIfModifiedSince());
|
||||||
if (modifiedSince.isAfter(object.getMetadata().getLastModified()))
|
if (modifiedSince.isAfter(object.getMetadata().getLastModified()))
|
||||||
throw new ExecutionException(new RuntimeException("after"));
|
throw new ExecutionException(new RuntimeException("after"));
|
||||||
|
|
||||||
}
|
}
|
||||||
if (options.getIfUnmodifiedSince() != null) {
|
if (options.getIfUnmodifiedSince() != null) {
|
||||||
DateTime unmodifiedSince = dateService.dateTimeFromHeaderFormat(options.getIfUnmodifiedSince());
|
DateTime unmodifiedSince = dateService.rfc822DateParse(options.getIfUnmodifiedSince());
|
||||||
if (unmodifiedSince.isAfter(object.getMetadata().getLastModified()))
|
if (unmodifiedSince.isAfter(object.getMetadata().getLastModified()))
|
||||||
throw new ExecutionException(new RuntimeException("after"));
|
throw new ExecutionException(new RuntimeException("after"));
|
||||||
}
|
}
|
||||||
|
@ -435,13 +435,13 @@ public class StubS3Connection implements S3Connection {
|
||||||
throwResponseException(304);
|
throwResponseException(304);
|
||||||
}
|
}
|
||||||
if (options.getIfModifiedSince() != null) {
|
if (options.getIfModifiedSince() != null) {
|
||||||
DateTime modifiedSince = dateService.dateTimeFromHeaderFormat(options.getIfModifiedSince());
|
DateTime modifiedSince = dateService.rfc822DateParse(options.getIfModifiedSince());
|
||||||
if (modifiedSince.isAfter(object.getMetadata().getLastModified()))
|
if (modifiedSince.isAfter(object.getMetadata().getLastModified()))
|
||||||
throw new ExecutionException(new RuntimeException("after"));
|
throw new ExecutionException(new RuntimeException("after"));
|
||||||
|
|
||||||
}
|
}
|
||||||
if (options.getIfUnmodifiedSince() != null) {
|
if (options.getIfUnmodifiedSince() != null) {
|
||||||
DateTime unmodifiedSince = dateService.dateTimeFromHeaderFormat(options.getIfUnmodifiedSince());
|
DateTime unmodifiedSince = dateService.rfc822DateParse(options.getIfUnmodifiedSince());
|
||||||
if (unmodifiedSince.isAfter(object.getMetadata().getLastModified()))
|
if (unmodifiedSince.isAfter(object.getMetadata().getLastModified()))
|
||||||
throw new ExecutionException(new RuntimeException("after"));
|
throw new ExecutionException(new RuntimeException("after"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ public class CopyObjectOptionsTest {
|
||||||
badMeta.put("x-google-meta-adrian", "foo");
|
badMeta.put("x-google-meta-adrian", "foo");
|
||||||
|
|
||||||
now = new DateTime();
|
now = new DateTime();
|
||||||
nowExpected = new DateService().toHeaderString(now);
|
nowExpected = new DateService().rfc822DateFormat(now);
|
||||||
testBytes = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
|
testBytes = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ public class CopyObjectOptionsTest {
|
||||||
.ifSourceMd5DoesntMatch(testBytes).overrideMetadataWith(
|
.ifSourceMd5DoesntMatch(testBytes).overrideMetadataWith(
|
||||||
goodMeta).buildRequestHeaders();
|
goodMeta).buildRequestHeaders();
|
||||||
assertEquals(headers.get("x-amz-copy-source-if-modified-since")
|
assertEquals(headers.get("x-amz-copy-source-if-modified-since")
|
||||||
.iterator().next(), new DateService().toHeaderString(now));
|
.iterator().next(), new DateService().rfc822DateFormat(now));
|
||||||
assertEquals(headers.get("x-amz-copy-source-if-none-match").iterator()
|
assertEquals(headers.get("x-amz-copy-source-if-none-match").iterator()
|
||||||
.next(), "\"" + S3Utils.toHexString(testBytes) + "\"");
|
.next(), "\"" + S3Utils.toHexString(testBytes) + "\"");
|
||||||
for (String value : goodMeta.values())
|
for (String value : goodMeta.values())
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class GetObjectOptionsTest {
|
||||||
@BeforeTest
|
@BeforeTest
|
||||||
void setUp() {
|
void setUp() {
|
||||||
now = new DateTime();
|
now = new DateTime();
|
||||||
nowExpected = new DateService().toHeaderString(now);
|
nowExpected = new DateService().rfc822DateFormat(now);
|
||||||
testBytes = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
|
testBytes = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,161 +23,283 @@
|
||||||
*/
|
*/
|
||||||
package com.amazon.s3;
|
package com.amazon.s3;
|
||||||
|
|
||||||
import com.google.inject.Guice;
|
|
||||||
import com.google.inject.Injector;
|
|
||||||
import org.jclouds.aws.PerformanceTest;
|
|
||||||
import org.jclouds.aws.s3.util.DateService;
|
|
||||||
import org.joda.time.DateTime;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.SimpleTimeZone;
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.CompletionService;
|
import java.util.concurrent.CompletionService;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorCompletionService;
|
import java.util.concurrent.ExecutorCompletionService;
|
||||||
|
|
||||||
|
import org.jclouds.aws.PerformanceTest;
|
||||||
|
import org.jclouds.aws.s3.util.DateService;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
import org.joda.time.DateTimeZone;
|
||||||
|
import org.joda.time.format.DateTimeFormat;
|
||||||
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Scrap any non-DateService references (eg Joda & Amazon) if/when
|
||||||
|
* we confirm that using the Java primitives is better/faster.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares performance of date operations
|
* Compares performance of date operations
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
* @author James Murty
|
||||||
*/
|
*/
|
||||||
@Test(sequential = true, timeOut = 2 * 60 * 1000, testName = "s3.DateTest")
|
@Test(sequential = true, timeOut = 2 * 60 * 1000, testName = "s3.DateTest")
|
||||||
public class DateServiceTest extends PerformanceTest {
|
public class DateServiceTest extends PerformanceTest {
|
||||||
Injector i = Guice.createInjector();
|
Injector i = Guice.createInjector();
|
||||||
|
|
||||||
DateService utils = i.getInstance(DateService.class);
|
DateService dateService = i.getInstance(DateService.class);
|
||||||
SimpleDateFormat dateParser;
|
|
||||||
|
private TestData[] testData;
|
||||||
|
class TestData {
|
||||||
|
public final String iso8601DateString;
|
||||||
|
public final String rfc822DateString;
|
||||||
|
public final Date date;
|
||||||
|
|
||||||
|
TestData(String iso8601, String rfc822, Date date) {
|
||||||
|
this.iso8601DateString = iso8601;
|
||||||
|
this.rfc822DateString = rfc822;
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long startTime;
|
||||||
|
|
||||||
|
|
||||||
public DateServiceTest() {
|
public DateServiceTest() {
|
||||||
this.dateParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
// Constant time test values, each TestData item must contain matching times!
|
||||||
this.dateParser.setTimeZone(new SimpleTimeZone(0, "GMT"));
|
testData = new TestData[] {
|
||||||
|
new TestData("2009-03-12T02:00:07.000Z", "Thu, 12 Mar 2009 02:00:07 GMT", new Date(1236823207000l)),
|
||||||
|
new TestData("2009-03-14T04:00:07.000Z", "Sat, 14 Mar 2009 04:00:07 GMT", new Date(1237003207000l)),
|
||||||
|
new TestData("2009-03-16T06:00:07.000Z", "Mon, 16 Mar 2009 06:00:07 GMT", new Date(1237183207000l)),
|
||||||
|
new TestData("2009-03-18T08:00:07.000Z", "Wed, 18 Mar 2009 08:00:07 GMT", new Date(1237363207000l)),
|
||||||
|
new TestData("2009-03-20T10:00:07.000Z", "Fri, 20 Mar 2009 10:00:07 GMT", new Date(1237543207000l))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Joda items for performance comparisons
|
||||||
|
private DateTimeFormatter headerDateFormat = DateTimeFormat
|
||||||
|
.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'");
|
||||||
|
|
||||||
|
private DateTime jodaParseIso8601(String toParse) {
|
||||||
|
return new DateTime(toParse);
|
||||||
}
|
}
|
||||||
|
|
||||||
Date amazonDateFromString(String toParse) throws ParseException {
|
private DateTime jodaParseRfc822(String toParse) {
|
||||||
return this.dateParser.parse(toParse);
|
return headerDateFormat.parseDateTime(toParse);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String toParse = "2009-03-12T02:00:07.000Z";
|
private String timestampAsHeaderString() {
|
||||||
|
return toHeaderString(new DateTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toHeaderString(DateTime date) {
|
||||||
|
return headerDateFormat.print(date.withZone(DateTimeZone.UTC));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void startClock() {
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printElapsedClockTime(String testName) {
|
||||||
|
System.out.println(testName + " took " +
|
||||||
|
(System.currentTimeMillis() - startTime) + "ms for "
|
||||||
|
+ LOOP_COUNT+ " loops");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseDateSameAsAmazon() throws ParseException,
|
public void testIso8601DateParse() throws ExecutionException,
|
||||||
ExecutionException, InterruptedException {
|
InterruptedException
|
||||||
Date java = dateParser.parse(toParse);
|
{
|
||||||
DateTime joda = utils.dateTimeFromXMLFormat(toParse);
|
DateTime dsDate = dateService.iso8601DateParse(testData[0].iso8601DateString);
|
||||||
assert java.equals(joda.toDate());
|
assert testData[0].date.equals(dsDate.toDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTimeStampDateSameAsAmazon() throws ExecutionException,
|
public void testRfc822DateParse() throws ExecutionException,
|
||||||
InterruptedException {
|
InterruptedException
|
||||||
String java = AWSAuthConnection.httpDate();
|
{
|
||||||
String joda = utils.timestampAsHeaderString();
|
DateTime dsDate = dateService.rfc822DateParse(testData[0].rfc822DateString);
|
||||||
assert java.equals(joda);
|
assert testData[0].date.equals(dsDate.toDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testToHeaderString() throws ExecutionException,
|
public void testIso8601DateFormat() throws ExecutionException,
|
||||||
InterruptedException {
|
InterruptedException
|
||||||
String joda1 = utils.toHeaderString(new DateTime());
|
{
|
||||||
String joda = utils.timestampAsHeaderString();
|
String dsString = dateService.iso8601DateFormat(testData[0].date);
|
||||||
assert joda1.equals(joda);
|
assert testData[0].iso8601DateString.equals(dsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testTimeStampSerialResponseTime() throws ExecutionException,
|
public void testRfc822DateFormat() throws ExecutionException,
|
||||||
InterruptedException {
|
InterruptedException
|
||||||
for (int i = 0; i < LOOP_COUNT; i++)
|
{
|
||||||
utils.timestampAsHeaderString();
|
String dsString = dateService.rfc822DateFormat(testData[0].date);
|
||||||
|
assert testData[0].rfc822DateString.equals(dsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testAmazonTimeStampSerialResponseTime() {
|
void testIso8601DateFormatResponseTime() throws ExecutionException,
|
||||||
for (int i = 0; i < LOOP_COUNT; i++)
|
InterruptedException {
|
||||||
AWSAuthConnection.httpDate();
|
for (int i = 0; i < LOOP_COUNT; i++)
|
||||||
|
dateService.iso8601DateFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testTimeStampParallelResponseTime() throws InterruptedException,
|
void testRfc822DateFormatResponseTime() throws ExecutionException,
|
||||||
ExecutionException {
|
InterruptedException {
|
||||||
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
|
for (int i = 0; i < LOOP_COUNT; i++)
|
||||||
exec);
|
dateService.rfc822DateFormat();
|
||||||
for (int i = 0; i < LOOP_COUNT; i++)
|
}
|
||||||
completer.submit(new Callable<Boolean>() {
|
|
||||||
public Boolean call() throws ExecutionException,
|
@Test
|
||||||
InterruptedException {
|
void testFormatIso8601DateInParallel() throws InterruptedException,
|
||||||
utils.timestampAsHeaderString();
|
ExecutionException {
|
||||||
return true;
|
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
|
||||||
}
|
exec);
|
||||||
});
|
startClock();
|
||||||
for (int i = 0; i < LOOP_COUNT; i++)
|
for (int i = 0; i < LOOP_COUNT; i++) {
|
||||||
assert completer.take().get();
|
final TestData myData = testData[i % testData.length];
|
||||||
|
completer.submit(new Callable<Boolean>() {
|
||||||
|
public Boolean call() throws ExecutionException,
|
||||||
|
InterruptedException
|
||||||
|
{
|
||||||
|
String dsString = dateService.iso8601DateFormat(myData.date);
|
||||||
|
/*
|
||||||
|
* Comment-in the assert below to test thread safety.
|
||||||
|
* Comment it out to test performance
|
||||||
|
*/
|
||||||
|
assert myData.iso8601DateString.equals(dsString);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (int i = 0; i < LOOP_COUNT; i++)
|
||||||
|
assert completer.take().get();
|
||||||
|
printElapsedClockTime("testFormatIso8601DateInParallel");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testAmazonTimeStampParallelResponseTime() throws InterruptedException,
|
void testFormatAmazonDateInParallel() throws InterruptedException,
|
||||||
ExecutionException {
|
ExecutionException {
|
||||||
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
|
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
|
||||||
exec);
|
exec);
|
||||||
for (int i = 0; i < LOOP_COUNT; i++)
|
startClock();
|
||||||
completer.submit(new Callable<Boolean>() {
|
for (int i = 0; i < LOOP_COUNT; i++)
|
||||||
public Boolean call() {
|
completer.submit(new Callable<Boolean>() {
|
||||||
AWSAuthConnection.httpDate();
|
public Boolean call() {
|
||||||
return true;
|
AWSAuthConnection.httpDate();
|
||||||
}
|
return true;
|
||||||
});
|
}
|
||||||
for (int i = 0; i < LOOP_COUNT; i++)
|
});
|
||||||
assert completer.take().get();
|
for (int i = 0; i < LOOP_COUNT; i++)
|
||||||
|
assert completer.take().get();
|
||||||
|
printElapsedClockTime("testFormatAmazonDateInParallel");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParseDateSerialResponseTime() throws ExecutionException,
|
void testFormatJodaDateInParallel() throws InterruptedException,
|
||||||
InterruptedException {
|
ExecutionException {
|
||||||
for (int i = 0; i < LOOP_COUNT; i++)
|
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
|
||||||
utils.dateTimeFromXMLFormat(toParse);
|
exec);
|
||||||
|
startClock();
|
||||||
|
for (int i = 0; i < LOOP_COUNT; i++) {
|
||||||
|
final TestData myData = testData[i % testData.length];
|
||||||
|
completer.submit(new Callable<Boolean>() {
|
||||||
|
public Boolean call() {
|
||||||
|
String jodaString = toHeaderString(new DateTime(myData.date));
|
||||||
|
assert myData.rfc822DateString.equals(jodaString);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (int i = 0; i < LOOP_COUNT; i++)
|
||||||
|
assert completer.take().get();
|
||||||
|
printElapsedClockTime("testFormatJodaDateInParallel");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testIso8601ParseDateSerialResponseTime() throws ExecutionException,
|
||||||
|
InterruptedException {
|
||||||
|
for (int i = 0; i < LOOP_COUNT; i++)
|
||||||
|
dateService.iso8601DateParse(testData[0].iso8601DateString);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testAmazonParseDateSerialResponseTime() {
|
void testAmazonParseDateSerialResponseTime() {
|
||||||
for (int i = 0; i < LOOP_COUNT; i++)
|
for (int i = 0; i < LOOP_COUNT; i++)
|
||||||
AWSAuthConnection.httpDate();
|
AWSAuthConnection.httpDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParseDateParallelResponseTime() throws InterruptedException,
|
void testParseIso8601DateInParallel() throws InterruptedException,
|
||||||
ExecutionException {
|
ExecutionException {
|
||||||
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
|
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
|
||||||
exec);
|
exec);
|
||||||
|
startClock();
|
||||||
for (int i = 0; i < LOOP_COUNT; i++)
|
for (int i = 0; i < LOOP_COUNT; i++) {
|
||||||
completer.submit(new Callable<Boolean>() {
|
final TestData myData = testData[i % testData.length];
|
||||||
public Boolean call() throws ExecutionException,
|
completer.submit(new Callable<Boolean>() {
|
||||||
InterruptedException {
|
public Boolean call() throws ExecutionException,
|
||||||
utils.dateTimeFromXMLFormat(toParse);
|
InterruptedException {
|
||||||
return true;
|
DateTime dsDate = dateService.iso8601DateParse(myData.iso8601DateString);
|
||||||
}
|
assert myData.date.equals(dsDate.toDate());
|
||||||
});
|
return true;
|
||||||
for (int i = 0; i < LOOP_COUNT; i++)
|
}
|
||||||
assert completer.take().get();
|
});
|
||||||
|
}
|
||||||
|
for (int i = 0; i < LOOP_COUNT; i++)
|
||||||
|
assert completer.take().get();
|
||||||
|
printElapsedClockTime("testParseIso8601DateInParallel");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testAmazonParseDateParallelResponseTime() throws InterruptedException,
|
void testParseAmazonDateInParallel() throws InterruptedException,
|
||||||
ExecutionException {
|
ExecutionException {
|
||||||
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
|
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
|
||||||
exec);
|
exec);
|
||||||
|
startClock();
|
||||||
|
for (int i = 0; i < LOOP_COUNT; i++)
|
||||||
|
completer.submit(new Callable<Boolean>() {
|
||||||
|
public Boolean call() {
|
||||||
|
AWSAuthConnection.httpDate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for (int i = 0; i < LOOP_COUNT; i++)
|
||||||
|
assert completer.take().get();
|
||||||
|
printElapsedClockTime("testParseAmazonDateInParallel");
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < LOOP_COUNT; i++)
|
@Test
|
||||||
completer.submit(new Callable<Boolean>() {
|
void testParseJodaDateInParallel() throws InterruptedException,
|
||||||
public Boolean call() {
|
ExecutionException {
|
||||||
AWSAuthConnection.httpDate();
|
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
|
||||||
return true;
|
exec);
|
||||||
}
|
startClock();
|
||||||
});
|
for (int i = 0; i < LOOP_COUNT; i++) {
|
||||||
for (int i = 0; i < LOOP_COUNT; i++)
|
final TestData myData = testData[i % testData.length];
|
||||||
assert completer.take().get();
|
completer.submit(new Callable<Boolean>() {
|
||||||
|
public Boolean call() {
|
||||||
|
Date jodaDate = jodaParseIso8601(myData.iso8601DateString).toDate();
|
||||||
|
assert myData.date.equals(jodaDate);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (int i = 0; i < LOOP_COUNT; i++)
|
||||||
|
assert completer.take().get();
|
||||||
|
printElapsedClockTime("testParseJodaDateInParallel");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue