From 7c3518f7fff341474263999bce1a6e6e3bb14736 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Thu, 22 Jul 2010 15:35:03 -0700 Subject: [PATCH] Issue 191: changed encryption service so that it can decode a PEM key. updated chef to work in google appengine --- .../handlers/AWSClientErrorRetryHandler.java | 2 +- .../ParseObjectMetadataFromHeadersTest.java | 20 +- .../aws/s3/xml/ListBucketHandlerTest.java | 109 +++++------ .../jclouds/aws/sqs/SQSClientLiveTest.java | 25 ++- .../internal/BaseBlobIntegrationTest.java | 112 ++++++----- .../BaseBlobStoreIntegrationTest.java | 127 +++++++------ .../BaseContainerIntegrationTest.java | 45 ++--- chef/pom.xml | 178 +++++++++--------- .../chef/config/BaseChefRestClientModule.java | 28 +-- .../handlers/ChefClientErrorRetryHandler.java | 72 +++++++ .../org/jclouds/chef/ChefClientLiveTest.java | 2 +- .../chef/filters/SignedHeaderAuthTest.java | 113 ++++------- .../ChefClientErrorRetryHandlerTest.java | 101 ++++++++++ core/pom.xml | 11 ++ .../jclouds/encryption/EncryptionService.java | 3 + .../internal/BaseEncryptionService.java | 51 ++++- .../internal/JCEEncryptionService.java | 9 + .../java/org/jclouds/http/BaseJettyTest.java | 75 ++++---- .../http/filters/BasicAuthenticationTest.java | 7 +- .../jclouds/http/internal/WireLiveTest.java | 25 ++- .../BouncyCastleEncryptionService.java | 9 + .../jclouds/gae/ConvertToGaeRequestTest.java | 14 +- .../gae/ConvertToJcloudsResponseTest.java | 14 +- .../cloudfiles/CloudFilesClientLiveTest.java | 14 +- 24 files changed, 718 insertions(+), 448 deletions(-) create mode 100644 chef/src/main/java/org/jclouds/chef/handlers/ChefClientErrorRetryHandler.java create mode 100644 chef/src/test/java/org/jclouds/chef/handlers/ChefClientErrorRetryHandlerTest.java diff --git a/aws/core/src/main/java/org/jclouds/aws/handlers/AWSClientErrorRetryHandler.java b/aws/core/src/main/java/org/jclouds/aws/handlers/AWSClientErrorRetryHandler.java index 7bc7db1010..60dea2336d 100755 --- a/aws/core/src/main/java/org/jclouds/aws/handlers/AWSClientErrorRetryHandler.java +++ b/aws/core/src/main/java/org/jclouds/aws/handlers/AWSClientErrorRetryHandler.java @@ -34,7 +34,7 @@ import org.jclouds.logging.Logger; import com.google.inject.Inject; /** - * Handles Retryable responses with error codes in the 3xx range + * Handles Retryable responses with error codes in the 4xx range * * @author Adrian Cole */ diff --git a/aws/core/src/test/java/org/jclouds/aws/s3/functions/ParseObjectMetadataFromHeadersTest.java b/aws/core/src/test/java/org/jclouds/aws/s3/functions/ParseObjectMetadataFromHeadersTest.java index fb79594b07..f43ac43c04 100644 --- a/aws/core/src/test/java/org/jclouds/aws/s3/functions/ParseObjectMetadataFromHeadersTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/s3/functions/ParseObjectMetadataFromHeadersTest.java @@ -23,6 +23,7 @@ import static org.easymock.classextension.EasyMock.createMock; import static org.easymock.classextension.EasyMock.replay; import static org.testng.Assert.assertEquals; +import java.security.NoSuchAlgorithmException; import java.util.Date; import java.util.Map; @@ -42,6 +43,7 @@ import org.jclouds.io.Payloads; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableMap; /** @@ -49,7 +51,15 @@ import com.google.common.collect.ImmutableMap; */ @Test(testName = "s3.ParseObjectMetadataFromHeadersTest") public class ParseObjectMetadataFromHeadersTest { - private static final EncryptionService encryptionService = new JCEEncryptionService(); + + protected volatile static EncryptionService encryptionService; + static { + try { + encryptionService = new JCEEncryptionService(); + } catch (NoSuchAlgorithmException e) { + Throwables.propagate(e); + } + } @Test void testNormal() throws Exception { @@ -59,8 +69,8 @@ public class ParseObjectMetadataFromHeadersTest { http.getHeaders().put(HttpHeaders.CACHE_CONTROL, "cacheControl"); http.getHeaders().put("Content-Disposition", "contentDisposition"); http.getHeaders().put(HttpHeaders.CONTENT_ENCODING, "encoding"); - ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http, - "\"abc\""), blobToObjectMetadata, encryptionService, "x-amz-meta-"); + ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http, "\"abc\""), + blobToObjectMetadata, encryptionService, "x-amz-meta-"); MutableObjectMetadata response = parser.apply(http); assertEquals(response, expects); } @@ -75,8 +85,8 @@ public class ParseObjectMetadataFromHeadersTest { http.getHeaders().put("Content-Disposition", "contentDisposition"); http.getHeaders().put(HttpHeaders.CONTENT_ENCODING, "encoding"); http.getHeaders().put("x-amz-meta-object-eTag", "\"abc\""); - ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http, - null), blobToObjectMetadata, encryptionService, "x-amz-meta-"); + ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http, null), + blobToObjectMetadata, encryptionService, "x-amz-meta-"); MutableObjectMetadata response = parser.apply(http); assertEquals(response, expects); } diff --git a/aws/core/src/test/java/org/jclouds/aws/s3/xml/ListBucketHandlerTest.java b/aws/core/src/test/java/org/jclouds/aws/s3/xml/ListBucketHandlerTest.java index 35d828bc93..323b10d445 100755 --- a/aws/core/src/test/java/org/jclouds/aws/s3/xml/ListBucketHandlerTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/s3/xml/ListBucketHandlerTest.java @@ -21,6 +21,7 @@ package org.jclouds.aws.s3.xml; import static org.testng.Assert.assertEquals; import java.io.InputStream; +import java.security.NoSuchAlgorithmException; import java.util.TreeSet; import org.jclouds.aws.s3.domain.CanonicalUser; @@ -39,6 +40,7 @@ import org.jclouds.util.Utils; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; @Test(groups = "unit", testName = "s3.ListBucketHandlerTest") @@ -46,7 +48,15 @@ public class ListBucketHandlerTest extends BaseHandlerTest { public static final String listBucketWithPrefixAppsSlash = "adriancole.org.jclouds.aws.s3.amazons3testdelimiterapps/1000falseapps/02009-05-07T18:27:08.000Z"c82e6a0025c31c5de5947fda62ac51ab"8e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0ferncamSTANDARDapps/12009-05-07T18:27:09.000Z"944fab2c5a9a6bacf07db5e688310d7a"8e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0ferncamSTANDARDapps/22009-05-07T18:27:09.000Z"a227b8888045c8fd159fb495214000f0"8e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0ferncamSTANDARDapps/32009-05-07T18:27:09.000Z"c9caa76c3dec53e2a192608ce73eef03"8e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0ferncamSTANDARDapps/42009-05-07T18:27:09.000Z"1ce5d0dcc6154a647ea90c7bdf82a224"8e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0ferncamSTANDARDapps/52009-05-07T18:27:09.000Z"79433524d87462ee05708a8ef894ed55"8e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0ferncamSTANDARDapps/62009-05-07T18:27:10.000Z"dd00a060b28ddca8bc5a21a49e306f67"8e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0ferncamSTANDARDapps/72009-05-07T18:27:10.000Z"8cd06eca6e819a927b07a285d750b100"8e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0ferncamSTANDARDapps/82009-05-07T18:27:10.000Z"174495094d0633b92cbe46603eee6bad"8e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0ferncamSTANDARDapps/92009-05-07T18:27:10.000Z"cd8a19b26fea8a827276df0ad11c580d"8e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0ferncamSTANDARD"; public static final String listBucketWithSlashDelimiterAndCommonPrefixApps = " / apps/"; private DateService dateService; - private static final EncryptionService encryptionService = new JCEEncryptionService(); + + protected volatile static EncryptionService encryptionService; + static { + try { + encryptionService = new JCEEncryptionService(); + } catch (NoSuchAlgorithmException e) { + Throwables.propagate(e); + } + } @BeforeTest @Override @@ -58,71 +68,57 @@ public class ListBucketHandlerTest extends BaseHandlerTest { public void testApplyInputStream() { InputStream is = getClass().getResourceAsStream("/s3/list_bucket.xml"); - CanonicalUser owner = new CanonicalUser( - "e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0", "ferncam"); - ListBucketResponse expected = new ListBucketResponseImpl( - "adriancole.org.jclouds.aws.s3.amazons3testdelimiter", ImmutableList.of( + CanonicalUser owner = new CanonicalUser("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0", + "ferncam"); + ListBucketResponse expected = new ListBucketResponseImpl("adriancole.org.jclouds.aws.s3.amazons3testdelimiter", + ImmutableList + .of( (ObjectMetadata) new BucketListObjectMetadata("apps/0", dateService - .iso8601DateParse("2009-05-07T18:27:08.000Z"), - "\"c82e6a0025c31c5de5947fda62ac51ab\"", encryptionService - .fromHex("c82e6a0025c31c5de5947fda62ac51ab"), 8, owner, - StorageClass.STANDARD), - (ObjectMetadata) new BucketListObjectMetadata("apps/1", dateService - .iso8601DateParse("2009-05-07T18:27:09.000Z"), - "\"944fab2c5a9a6bacf07db5e688310d7a\"", encryptionService - .fromHex("944fab2c5a9a6bacf07db5e688310d7a"), 8, owner, - StorageClass.STANDARD), + .iso8601DateParse("2009-05-07T18:27:08.000Z"), "\"c82e6a0025c31c5de5947fda62ac51ab\"", + encryptionService.fromHex("c82e6a0025c31c5de5947fda62ac51ab"), 8, owner, + StorageClass.STANDARD), (ObjectMetadata) new BucketListObjectMetadata("apps/1", + dateService.iso8601DateParse("2009-05-07T18:27:09.000Z"), + "\"944fab2c5a9a6bacf07db5e688310d7a\"", encryptionService + .fromHex("944fab2c5a9a6bacf07db5e688310d7a"), 8, owner, StorageClass.STANDARD), (ObjectMetadata) new BucketListObjectMetadata("apps/2", dateService - .iso8601DateParse("2009-05-07T18:27:09.000Z"), - "\"a227b8888045c8fd159fb495214000f0\"", encryptionService - .fromHex("a227b8888045c8fd159fb495214000f0"), 8, owner, - StorageClass.STANDARD), - (ObjectMetadata) new BucketListObjectMetadata("apps/3", dateService - .iso8601DateParse("2009-05-07T18:27:09.000Z"), - "\"c9caa76c3dec53e2a192608ce73eef03\"", encryptionService - .fromHex("c9caa76c3dec53e2a192608ce73eef03"), 8, owner, - StorageClass.STANDARD), + .iso8601DateParse("2009-05-07T18:27:09.000Z"), "\"a227b8888045c8fd159fb495214000f0\"", + encryptionService.fromHex("a227b8888045c8fd159fb495214000f0"), 8, owner, + StorageClass.STANDARD), (ObjectMetadata) new BucketListObjectMetadata("apps/3", + dateService.iso8601DateParse("2009-05-07T18:27:09.000Z"), + "\"c9caa76c3dec53e2a192608ce73eef03\"", encryptionService + .fromHex("c9caa76c3dec53e2a192608ce73eef03"), 8, owner, StorageClass.STANDARD), (ObjectMetadata) new BucketListObjectMetadata("apps/4", dateService - .iso8601DateParse("2009-05-07T18:27:09.000Z"), - "\"1ce5d0dcc6154a647ea90c7bdf82a224\"", encryptionService - .fromHex("1ce5d0dcc6154a647ea90c7bdf82a224"), 8, owner, - StorageClass.STANDARD), - (ObjectMetadata) new BucketListObjectMetadata("apps/5", dateService - .iso8601DateParse("2009-05-07T18:27:09.000Z"), - "\"79433524d87462ee05708a8ef894ed55\"", encryptionService - .fromHex("79433524d87462ee05708a8ef894ed55"), 8, owner, - StorageClass.STANDARD), + .iso8601DateParse("2009-05-07T18:27:09.000Z"), "\"1ce5d0dcc6154a647ea90c7bdf82a224\"", + encryptionService.fromHex("1ce5d0dcc6154a647ea90c7bdf82a224"), 8, owner, + StorageClass.STANDARD), (ObjectMetadata) new BucketListObjectMetadata("apps/5", + dateService.iso8601DateParse("2009-05-07T18:27:09.000Z"), + "\"79433524d87462ee05708a8ef894ed55\"", encryptionService + .fromHex("79433524d87462ee05708a8ef894ed55"), 8, owner, StorageClass.STANDARD), (ObjectMetadata) new BucketListObjectMetadata("apps/6", dateService - .iso8601DateParse("2009-05-07T18:27:10.000Z"), - "\"dd00a060b28ddca8bc5a21a49e306f67\"", encryptionService - .fromHex("dd00a060b28ddca8bc5a21a49e306f67"), 8, owner, - StorageClass.STANDARD), - (ObjectMetadata) new BucketListObjectMetadata("apps/7", dateService - .iso8601DateParse("2009-05-07T18:27:10.000Z"), - "\"8cd06eca6e819a927b07a285d750b100\"", encryptionService - .fromHex("8cd06eca6e819a927b07a285d750b100"), 8, owner, - StorageClass.STANDARD), + .iso8601DateParse("2009-05-07T18:27:10.000Z"), "\"dd00a060b28ddca8bc5a21a49e306f67\"", + encryptionService.fromHex("dd00a060b28ddca8bc5a21a49e306f67"), 8, owner, + StorageClass.STANDARD), (ObjectMetadata) new BucketListObjectMetadata("apps/7", + dateService.iso8601DateParse("2009-05-07T18:27:10.000Z"), + "\"8cd06eca6e819a927b07a285d750b100\"", encryptionService + .fromHex("8cd06eca6e819a927b07a285d750b100"), 8, owner, StorageClass.STANDARD), (ObjectMetadata) new BucketListObjectMetadata("apps/8", dateService - .iso8601DateParse("2009-05-07T18:27:10.000Z"), - "\"174495094d0633b92cbe46603eee6bad\"", encryptionService - .fromHex("174495094d0633b92cbe46603eee6bad"), 8, owner, - StorageClass.STANDARD), - (ObjectMetadata) new BucketListObjectMetadata("apps/9", dateService - .iso8601DateParse("2009-05-07T18:27:10.000Z"), - "\"cd8a19b26fea8a827276df0ad11c580d\"", encryptionService - .fromHex("cd8a19b26fea8a827276df0ad11c580d"), 8, owner, - StorageClass.STANDARD)), "apps/", null, null, 1000, null, false, - new TreeSet()); + .iso8601DateParse("2009-05-07T18:27:10.000Z"), "\"174495094d0633b92cbe46603eee6bad\"", + encryptionService.fromHex("174495094d0633b92cbe46603eee6bad"), 8, owner, + StorageClass.STANDARD), (ObjectMetadata) new BucketListObjectMetadata("apps/9", + dateService.iso8601DateParse("2009-05-07T18:27:10.000Z"), + "\"cd8a19b26fea8a827276df0ad11c580d\"", encryptionService + .fromHex("cd8a19b26fea8a827276df0ad11c580d"), 8, owner, StorageClass.STANDARD)), + "apps/", null, null, 1000, null, false, new TreeSet()); - ListBucketResponse result = (ListBucketResponse) factory.create( - injector.getInstance(ListBucketHandler.class)).parse(is); + ListBucketResponse result = (ListBucketResponse) factory.create(injector.getInstance(ListBucketHandler.class)) + .parse(is); assertEquals(result, expected); } ParseSax createParser() { ParseSax parser = (ParseSax) factory.create(injector - .getInstance(ListBucketHandler.class)); + .getInstance(ListBucketHandler.class)); return parser; } @@ -130,7 +126,7 @@ public class ListBucketHandlerTest extends BaseHandlerTest { public void testListMyBucketsWithDelimiterSlashAndCommonPrefixesAppsSlash() throws HttpException { ListBucketResponse bucket = createParser().parse( - Utils.toInputStream(listBucketWithSlashDelimiterAndCommonPrefixApps)); + Utils.toInputStream(listBucketWithSlashDelimiterAndCommonPrefixApps)); assertEquals(bucket.getCommonPrefixes().iterator().next(), "apps/"); assertEquals(bucket.getDelimiter(), "/"); assert bucket.getMarker() == null; @@ -139,8 +135,7 @@ public class ListBucketHandlerTest extends BaseHandlerTest { @Test public void testListMyBucketsWithPrefixAppsSlash() throws HttpException { - ListBucketResponse bucket = createParser().parse( - Utils.toInputStream(listBucketWithPrefixAppsSlash)); + ListBucketResponse bucket = createParser().parse(Utils.toInputStream(listBucketWithPrefixAppsSlash)); assertEquals(bucket.getPrefix(), "apps/"); assertEquals(bucket.getMaxKeys(), 1000); assert bucket.getMarker() == null; diff --git a/aws/core/src/test/java/org/jclouds/aws/sqs/SQSClientLiveTest.java b/aws/core/src/test/java/org/jclouds/aws/sqs/SQSClientLiveTest.java index 5c88a2aef3..0640245dad 100644 --- a/aws/core/src/test/java/org/jclouds/aws/sqs/SQSClientLiveTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/sqs/SQSClientLiveTest.java @@ -24,6 +24,7 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import java.io.IOException; +import java.security.NoSuchAlgorithmException; import java.util.Set; import java.util.SortedSet; @@ -40,6 +41,7 @@ import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.google.inject.Module; @@ -57,7 +59,15 @@ public class SQSClientLiveTest { private RestContext context; - private EncryptionService encryptionService = new JCEEncryptionService(); + protected volatile static EncryptionService encryptionService; + static { + try { + encryptionService = new JCEEncryptionService(); + } catch (NoSuchAlgorithmException e) { + Throwables.propagate(e); + } + } + private Set queues = Sets.newHashSet(); @BeforeGroups(groups = { "live" }) @@ -66,14 +76,14 @@ public class SQSClientLiveTest { String credential = checkNotNull(System.getProperty("jclouds.test.credential"), "jclouds.test.credential"); context = new RestContextFactory().createContext("sqs", identity, credential, ImmutableSet - . of(new Log4JLoggingModule())); + . of(new Log4JLoggingModule())); this.client = context.getApi(); } @Test void testListQueuesInRegion() throws InterruptedException { for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1, Region.US_WEST_1, - Region.AP_SOUTHEAST_1)) { + Region.AP_SOUTHEAST_1)) { SortedSet allResults = Sets.newTreeSet(client.listQueuesInRegion(region)); assertNotNull(allResults); if (allResults.size() >= 1) { @@ -90,7 +100,7 @@ public class SQSClientLiveTest { String queueName = PREFIX + "1"; for (final String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1, Region.US_WEST_1, - Region.AP_SOUTHEAST_1)) { + Region.AP_SOUTHEAST_1)) { try { SortedSet result = Sets.newTreeSet(client.listQueuesInRegion(region, queuePrefix(queueName))); if (result.size() >= 1) { @@ -147,8 +157,9 @@ public class SQSClientLiveTest { private static final int INCONSISTENCY_WINDOW = 10000; /** - * Due to eventual consistency, container commands may not return correctly immediately. Hence, - * we will try up to the inconsistency window to see if the assertion completes. + * Due to eventual consistency, container commands may not return correctly + * immediately. Hence, we will try up to the inconsistency window to see if + * the assertion completes. */ protected static void assertEventually(Runnable assertion) throws InterruptedException { long start = System.currentTimeMillis(); @@ -158,7 +169,7 @@ public class SQSClientLiveTest { assertion.run(); if (i > 0) System.err.printf("%d attempts and %dms asserting %s%n", i + 1, System.currentTimeMillis() - start, - assertion.getClass().getSimpleName()); + assertion.getClass().getSimpleName()); return; } catch (AssertionError e) { error = e; diff --git a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java index 200befd038..8be2accdcc 100755 --- a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java +++ b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java @@ -35,6 +35,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; import java.util.Date; import java.util.Map; import java.util.zip.GZIPInputStream; @@ -47,6 +48,7 @@ import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageType; +import org.jclouds.encryption.EncryptionService; import org.jclouds.encryption.internal.JCEEncryptionService; import org.jclouds.http.BaseJettyTest; import org.jclouds.http.HttpResponseException; @@ -61,6 +63,7 @@ import org.testng.annotations.Test; import com.google.common.base.Function; import com.google.common.base.Predicate; +import com.google.common.base.Throwables; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.io.ByteStreams; @@ -79,8 +82,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { @Override public void setUpResourcesOnThisThread(ITestContext testContext) throws Exception { super.setUpResourcesOnThisThread(testContext); - Payload result = context.utils().encryption().generatePayloadWithMD5For( - getTestDataSupplier().getInput()); + Payload result = context.utils().encryption().generatePayloadWithMD5For(getTestDataSupplier().getInput()); oneHundredOneConstitutions = (byte[]) result.getRawContent(); oneHundredOneConstitutionsMD5 = result.getContentMD5(); } @@ -88,9 +90,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { @SuppressWarnings("unchecked") public static InputSupplier getTestDataSupplier() throws IOException { byte[] oneConstitution = ByteStreams.toByteArray(new GZIPInputStream(BaseJettyTest.class - .getResourceAsStream("/const.txt.gz"))); - InputSupplier constitutionSupplier = ByteStreams - .newInputStreamSupplier(oneConstitution); + .getResourceAsStream("/const.txt.gz"))); + InputSupplier constitutionSupplier = ByteStreams.newInputStreamSupplier(oneConstitution); InputSupplier temp = ByteStreams.join(constitutionSupplier); @@ -110,20 +111,20 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { Map> responses = Maps.newHashMap(); for (int i = 0; i < 10; i++) { - responses.put(i, Futures.compose(context.getAsyncBlobStore() - .getBlob(containerName, key), new Function() { + responses.put(i, Futures.compose(context.getAsyncBlobStore().getBlob(containerName, key), + new Function() { - @Override - public Void apply(Blob from) { - assertEquals(context.utils().encryption().md5(from.getPayload().getInput()), - oneHundredOneConstitutionsMD5); - return null; - } + @Override + public Void apply(Blob from) { + assertEquals(context.utils().encryption().md5(from.getPayload().getInput()), + oneHundredOneConstitutionsMD5); + return null; + } - })); + })); } - Map exceptions = awaitCompletion(responses, exec, 30000l, - Logger.CONSOLE, "get constitution"); + Map exceptions = awaitCompletion(responses, exec, 30000l, Logger.CONSOLE, + "get constitution"); assert exceptions.size() == 0 : exceptions; } finally { @@ -250,10 +251,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { Blob blob1 = context.getBlobStore().getBlob(containerName, key, range(0, 5)); assertEquals(getContentAsStringOrNullAndClose(blob1), TEST_STRING.substring(0, 6)); - Blob blob2 = context.getBlobStore().getBlob(containerName, key, - range(6, TEST_STRING.length())); - assertEquals(getContentAsStringOrNullAndClose(blob2), TEST_STRING.substring(6, TEST_STRING - .length())); + Blob blob2 = context.getBlobStore().getBlob(containerName, key, range(6, TEST_STRING.length())); + assertEquals(getContentAsStringOrNullAndClose(blob2), TEST_STRING.substring(6, TEST_STRING.length())); } finally { returnContainer(containerName); } @@ -267,8 +266,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { String key = "apples"; addObjectAndValidateContent(containerName, key); - Blob blob = context.getBlobStore().getBlob(containerName, key, - range(0, 5).range(6, TEST_STRING.length())); + Blob blob = context.getBlobStore().getBlob(containerName, key, range(0, 5).range(6, TEST_STRING.length())); assertEquals(getContentAsStringOrNullAndClose(blob), TEST_STRING); } finally { @@ -277,7 +275,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { } // @Test(groups = { "integration", "live" }) - // public void testGetTail() throws InterruptedException, ExecutionException, TimeoutException, + // public void testGetTail() throws InterruptedException, ExecutionException, + // TimeoutException, // IOException { // String containerName = getContainerName(); // try { @@ -285,7 +284,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { // String key = "apples"; // // addObjectAndValidateContent(containerName, key); - // Blob blob = context.getBlobStore().getBlob(containerName, key, tail(5)).get(30, + // Blob blob = context.getBlobStore().getBlob(containerName, key, + // tail(5)).get(30, // TimeUnit.SECONDS); // assertEquals(BlobStoreUtils.getContentAsStringAndClose(blob), TEST_STRING // .substring(TEST_STRING.length() - 5)); @@ -297,7 +297,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { // } // @Test(groups = { "integration", "live" }) - // public void testGetStartAt() throws InterruptedException, ExecutionException, + // public void testGetStartAt() throws InterruptedException, + // ExecutionException, // TimeoutException, // IOException { // String containerName = getContainerName(); @@ -305,9 +306,11 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { // String key = "apples"; // // addObjectAndValidateContent(containerName, key); - // Blob blob = context.getBlobStore().getBlob(containerName, key, startAt(5)).get(30, + // Blob blob = context.getBlobStore().getBlob(containerName, key, + // startAt(5)).get(30, // TimeUnit.SECONDS); - // assertEquals(BlobStoreUtils.getContentAsStringAndClose(blob), TEST_STRING.substring(5, + // assertEquals(BlobStoreUtils.getContentAsStringAndClose(blob), + // TEST_STRING.substring(5, // TEST_STRING.length())); // assertEquals(blob.getContentLength(), TEST_STRING.length() - 5); // assertEquals(blob.getMetadata().getSize(), TEST_STRING.length()); @@ -316,8 +319,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { // } // } - private String addObjectAndValidateContent(String sourcecontainerName, String sourceKey) - throws InterruptedException { + private String addObjectAndValidateContent(String sourcecontainerName, String sourceKey) throws InterruptedException { String eTag = addBlobToContainer(sourcecontainerName, sourceKey); validateContent(sourcecontainerName, sourceKey); return eTag; @@ -347,9 +349,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { @DataProvider(name = "delete") public Object[][] createData() { - return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, - { "path/foo" }, { "colon:" }, { "asteri*k" }, { "quote\"" }, { "{greaten" }, { "p|pe" } }; + return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" }, + { "colon:" }, { "asteri*k" }, { "quote\"" }, { "{greaten" }, { "p|pe" } }; } @Test(groups = { "integration", "live" }, dataProvider = "delete") @@ -365,18 +366,18 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { } private void assertContainerEmptyDeleting(String containerName, String key) { - Iterable listing = Iterables.filter(context.getBlobStore().list( - containerName), new Predicate() { + Iterable listing = Iterables.filter(context.getBlobStore().list(containerName), + new Predicate() { - @Override - public boolean apply(StorageMetadata input) { - return input.getType() == StorageType.BLOB; - } + @Override + public boolean apply(StorageMetadata input) { + return input.getType() == StorageType.BLOB; + } - }); + }); assertEquals(Iterables.size(listing), 0, String.format( - "deleting %s, we still have %s blobs left in container %s, using encoding %s", key, - Iterables.size(listing), containerName, LOCAL_ENCODING)); + "deleting %s, we still have %s blobs left in container %s, using encoding %s", key, + Iterables.size(listing), containerName, LOCAL_ENCODING)); } @Test(groups = { "integration", "live" }) @@ -396,13 +397,13 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { String realObject = Utils.toStringAndClose(new FileInputStream("pom.xml")); return new Object[][] { { "file", "text/xml", new File("pom.xml"), realObject }, - { "string", "text/xml", realObject, realObject }, - { "bytes", "application/octet-stream", realObject.getBytes(), realObject } }; + { "string", "text/xml", realObject, realObject }, + { "bytes", "application/octet-stream", realObject.getBytes(), realObject } }; } @Test(groups = { "integration", "live" }, dataProvider = "putTests") - public void testPutObject(String key, String type, Object content, Object realObject) - throws InterruptedException, IOException { + public void testPutObject(String key, String type, Object content, Object realObject) throws InterruptedException, + IOException { Blob blob = context.getBlobStore().newBlob(key); blob.getMetadata().setContentType(type); blob.setPayload(Payloads.newPayload(content)); @@ -422,6 +423,15 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { } } + protected volatile static EncryptionService encryptionService; + static { + try { + encryptionService = new JCEEncryptionService(); + } catch (NoSuchAlgorithmException e) { + Throwables.propagate(e); + } + } + @Test(groups = { "integration", "live" }) public void testMetadata() throws InterruptedException { String key = "hello"; @@ -430,11 +440,11 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { blob.setPayload(TEST_STRING); blob.getMetadata().setContentType(MediaType.TEXT_PLAIN); blob.getMetadata().setSize(new Long(TEST_STRING.length())); - // NOTE all metadata in jclouds comes out as lowercase, in an effort to normalize the + // NOTE all metadata in jclouds comes out as lowercase, in an effort to + // normalize the // providers. blob.getMetadata().getUserMetadata().put("Adrian", "powderpuff"); - blob.getMetadata().setContentMD5( - new JCEEncryptionService().md5(Utils.toInputStream(TEST_STRING))); + blob.getMetadata().setContentMD5(encryptionService.md5(Utils.toInputStream(TEST_STRING))); String containerName = getContainerName(); try { assertNull(context.getBlobStore().blobMetadata(containerName, "powderpuff")); @@ -447,7 +457,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { validateMetadata(metadata); validateMetadata(context.getBlobStore().blobMetadata(containerName, key)); - // write 2 items with the same key to ensure that provider doesn't accept dupes + // write 2 items with the same key to ensure that provider doesn't + // accept dupes blob.getMetadata().getUserMetadata().put("Adrian", "wonderpuff"); blob.getMetadata().getUserMetadata().put("Adrian", "powderpuff"); @@ -463,8 +474,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { assert metadata.getContentType().startsWith("text/plain") : metadata.getContentType(); assertEquals(metadata.getSize(), new Long(TEST_STRING.length())); assertEquals(metadata.getUserMetadata().get("adrian"), "powderpuff"); - assertEquals(metadata.getContentMD5(), new JCEEncryptionService().md5(Utils - .toInputStream(TEST_STRING))); + assertEquals(metadata.getContentMD5(), encryptionService.md5(Utils.toInputStream(TEST_STRING))); } } \ No newline at end of file diff --git a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobStoreIntegrationTest.java b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobStoreIntegrationTest.java index 51423ba841..254b529f91 100644 --- a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobStoreIntegrationTest.java +++ b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobStoreIntegrationTest.java @@ -23,6 +23,7 @@ import static org.jclouds.blobstore.util.BlobStoreUtils.getContentAsStringOrNull import static org.testng.Assert.assertEquals; import java.io.IOException; +import java.security.NoSuchAlgorithmException; import java.util.Map; import java.util.Set; import java.util.Map.Entry; @@ -39,6 +40,8 @@ import org.jclouds.blobstore.attr.ConsistencyModel; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageType; +import org.jclouds.encryption.EncryptionService; +import org.jclouds.encryption.internal.JCEEncryptionService; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.testng.ITestContext; import org.testng.annotations.AfterClass; @@ -58,16 +61,14 @@ public class BaseBlobStoreIntegrationTest { protected static final String XML_STRING_FORMAT = " "; protected static final String TEST_STRING = String.format(XML_STRING_FORMAT, "apple"); - protected Map fiveStrings = ImmutableMap.of("one", String.format( - XML_STRING_FORMAT, "apple"), "two", String.format(XML_STRING_FORMAT, "bear"), "three", - String.format(XML_STRING_FORMAT, "candy"), "four", String.format(XML_STRING_FORMAT, - "dogma"), "five", String.format(XML_STRING_FORMAT, "emma")); + protected Map fiveStrings = ImmutableMap.of("one", String.format(XML_STRING_FORMAT, "apple"), "two", + String.format(XML_STRING_FORMAT, "bear"), "three", String.format(XML_STRING_FORMAT, "candy"), "four", String + .format(XML_STRING_FORMAT, "dogma"), "five", String.format(XML_STRING_FORMAT, "emma")); - protected Map fiveStringsUnderPath = ImmutableMap.of("path/1", String.format( - XML_STRING_FORMAT, "apple"), "path/2", String.format(XML_STRING_FORMAT, "bear"), - "path/3", String.format(XML_STRING_FORMAT, "candy"), "path/4", String.format( - XML_STRING_FORMAT, "dogma"), "path/5", String - .format(XML_STRING_FORMAT, "emma")); + protected Map fiveStringsUnderPath = ImmutableMap.of("path/1", String.format(XML_STRING_FORMAT, + "apple"), "path/2", String.format(XML_STRING_FORMAT, "bear"), "path/3", String.format(XML_STRING_FORMAT, + "candy"), "path/4", String.format(XML_STRING_FORMAT, "dogma"), "path/5", String.format(XML_STRING_FORMAT, + "emma")); public static long INCONSISTENCY_WINDOW = 10000; protected static volatile AtomicInteger containerIndex = new AtomicInteger(0); @@ -78,11 +79,20 @@ public class BaseBlobStoreIntegrationTest { /** * two test groups integration and live. */ - private volatile static BlockingQueue containerNames = new ArrayBlockingQueue( - containerCount); + private volatile static BlockingQueue containerNames = new ArrayBlockingQueue(containerCount); + + protected volatile static EncryptionService encryptionService; + static { + try { + encryptionService = new JCEEncryptionService(); + } catch (NoSuchAlgorithmException e) { + Throwables.propagate(e); + } + } /** - * There are a lot of retries here mainly from experience running inside amazon EC2. + * There are a lot of retries here mainly from experience running inside + * amazon EC2. */ @BeforeSuite public void setUpResourcesForAllThreads(ITestContext testContext) throws Exception { @@ -91,13 +101,10 @@ public class BaseBlobStoreIntegrationTest { } @SuppressWarnings("unchecked") - private BlobStoreContext getCloudResources(ITestContext testContext) - throws ClassNotFoundException, InstantiationException, IllegalAccessException, - Exception { - String initializerClass = checkNotNull(System.getProperty("jclouds.test.initializer"), - "jclouds.test.initializer"); - Class clazz = (Class) Class - .forName(initializerClass); + private BlobStoreContext getCloudResources(ITestContext testContext) throws ClassNotFoundException, + InstantiationException, IllegalAccessException, Exception { + String initializerClass = checkNotNull(System.getProperty("jclouds.test.initializer"), "jclouds.test.initializer"); + Class clazz = (Class) Class.forName(initializerClass); BaseTestInitializer initializer = clazz.newInstance(); return initializer.init(createHttpModule(), testContext); } @@ -105,10 +112,11 @@ public class BaseBlobStoreIntegrationTest { protected ExecutorService exec; /** - * we are doing this at a class level, as the context.getBlobStore() object is going to be shared - * for all methods in the class. We don't want to do this for group, as some test classes may - * want to have a different implementation of context.getBlobStore(). For example, one class may - * want non-blocking i/o and another class google appengine. + * we are doing this at a class level, as the context.getBlobStore() object + * is going to be shared for all methods in the class. We don't want to do + * this for group, as some test classes may want to have a different + * implementation of context.getBlobStore(). For example, one class may want + * non-blocking i/o and another class google appengine. */ @BeforeClass(groups = { "integration", "live" }) public void setUpResourcesOnThisThread(ITestContext testContext) throws Exception { @@ -127,8 +135,8 @@ public class BaseBlobStoreIntegrationTest { private static volatile boolean initialized = false; - protected void createContainersSharedByAllThreads(BlobStoreContext context, - ITestContext testContext) throws Exception { + protected void createContainersSharedByAllThreads(BlobStoreContext context, ITestContext testContext) + throws Exception { while (!initialized) { synchronized (BaseBlobStoreIntegrationTest.class) { if (!initialized) { @@ -143,7 +151,8 @@ public class BaseBlobStoreIntegrationTest { containerNames.put(containerName); } catch (Throwable e) { e.printStackTrace(); - // throw away the container and try again with the next index + // throw away the container and try again with the next + // index deleteContainerOrWarnIfUnable(context, containerName); containerCount++; } @@ -177,13 +186,13 @@ public class BaseBlobStoreIntegrationTest { protected static void deleteEverything(final BlobStoreContext context) throws Exception { try { for (int i = 0; i < 2; i++) { - Iterable testContainers = Iterables.filter(context - .getBlobStore().list(), new Predicate() { - public boolean apply(StorageMetadata input) { - return (input.getType() == StorageType.CONTAINER || input.getType() == StorageType.FOLDER) - && input.getName().startsWith(CONTAINER_PREFIX.toLowerCase()); - } - }); + Iterable testContainers = Iterables.filter(context.getBlobStore().list(), + new Predicate() { + public boolean apply(StorageMetadata input) { + return (input.getType() == StorageType.CONTAINER || input.getType() == StorageType.FOLDER) + && input.getName().startsWith(CONTAINER_PREFIX.toLowerCase()); + } + }); for (StorageMetadata container : testContainers) { deleteContainerOrWarnIfUnable(context, container.getName()); } @@ -200,11 +209,12 @@ public class BaseBlobStoreIntegrationTest { public static boolean SANITY_CHECK_RETURNED_BUCKET_NAME = false; /** - * Due to eventual consistency, container commands may not return correctly immediately. Hence, - * we will try up to the inconsistency window to see if the assertion completes. + * Due to eventual consistency, container commands may not return correctly + * immediately. Hence, we will try up to the inconsistency window to see if + * the assertion completes. */ protected static void assertConsistencyAware(BlobStoreContext context, Runnable assertion) - throws InterruptedException { + throws InterruptedException { if (context.getConsistencyModel() == ConsistencyModel.STRICT) { assertion.run(); return; @@ -229,8 +239,8 @@ public class BaseBlobStoreIntegrationTest { assertConsistencyAware(context, assertion); } - protected static void createContainerAndEnsureEmpty(BlobStoreContext context, - final String containerName) throws InterruptedException { + protected static void createContainerAndEnsureEmpty(BlobStoreContext context, final String containerName) + throws InterruptedException { context.getBlobStore().createContainerInLocation(null, containerName); if (context.getConsistencyModel() == ConsistencyModel.EVENTUAL) Thread.sleep(1000); @@ -249,8 +259,7 @@ public class BaseBlobStoreIntegrationTest { } protected void add5BlobsUnderPathAnd5UnderRootToContainer(String sourceContainer) { - for (Entry entry : Iterables.concat(fiveStrings.entrySet(), - fiveStringsUnderPath.entrySet())) { + for (Entry entry : Iterables.concat(fiveStrings.entrySet(), fiveStringsUnderPath.entrySet())) { Blob sourceObject = context.getBlobStore().newBlob(entry.getKey()); sourceObject.getMetadata().setContentType("text/xml"); sourceObject.setPayload(entry.getValue()); @@ -275,20 +284,19 @@ public class BaseBlobStoreIntegrationTest { } protected void assertConsistencyAwareContainerSize(final String containerName, final int count) - throws InterruptedException { + throws InterruptedException { assertConsistencyAware(new Runnable() { public void run() { try { assert context.getBlobStore().countBlobs(containerName) == count : String.format( - "expected only %d values in %s: %s", count, containerName, Sets - .newHashSet(Iterables.transform(context.getBlobStore().list( - containerName), new Function() { + "expected only %d values in %s: %s", count, containerName, Sets.newHashSet(Iterables.transform( + context.getBlobStore().list(containerName), new Function() { - public String apply(StorageMetadata from) { - return from.getName(); - } + public String apply(StorageMetadata from) { + return from.getName(); + } - }))); + }))); } catch (Exception e) { Throwables.propagateIfPossible(e); } @@ -304,9 +312,9 @@ public class BaseBlobStoreIntegrationTest { } /** - * requestor will create a container using the name returned from this. This method will take - * care not to exceed the maximum containers permitted by a provider by deleting an existing - * container first. + * requestor will create a container using the name returned from this. This + * method will take care not to exceed the maximum containers permitted by a + * provider by deleting an existing container first. * * @throws InterruptedException */ @@ -318,12 +326,13 @@ public class BaseBlobStoreIntegrationTest { if (containerName != null) { containerNames.add(containerName); /* - * Ensure that any returned container name actually exists on the server. Return of a - * non-existent container introduces subtle testing bugs, where later unrelated tests will - * fail. + * Ensure that any returned container name actually exists on the + * server. Return of a non-existent container introduces subtle testing + * bugs, where later unrelated tests will fail. * - * NOTE: This sanity check should only be run for Stub-based Integration testing -- it will - * *substantially* slow down tests on a real server over a network. + * NOTE: This sanity check should only be run for Stub-based + * Integration testing -- it will *substantially* slow down tests on a + * real server over a network. */ if (SANITY_CHECK_RETURNED_BUCKET_NAME) { if (!Iterables.any(context.getBlobStore().list(), new Predicate() { @@ -331,15 +340,15 @@ public class BaseBlobStoreIntegrationTest { return containerName.equals(md.getName()); } })) { - throw new IllegalStateException( - "Test returned the name of a non-existent container: " + containerName); + throw new IllegalStateException("Test returned the name of a non-existent container: " + containerName); } } } } /** - * abandon old container name instead of waiting for the container to be created. + * abandon old container name instead of waiting for the container to be + * created. * * @throws InterruptedException */ diff --git a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseContainerIntegrationTest.java b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseContainerIntegrationTest.java index 875091cf2d..a8c4a14163 100755 --- a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseContainerIntegrationTest.java +++ b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseContainerIntegrationTest.java @@ -37,7 +37,6 @@ import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; -import org.jclouds.encryption.internal.JCEEncryptionService; import org.testng.annotations.Test; /** @@ -48,8 +47,7 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest { @Test(groups = { "integration", "live" }) public void containerDoesntExist() { assert !context.getBlobStore().containerExists("forgetaboutit"); - assert !context.getBlobStore().containerExists( - "cloudcachestorefunctionalintegrationtest-first"); + assert !context.getBlobStore().containerExists("cloudcachestorefunctionalintegrationtest-first"); } @Test(groups = { "integration", "live" }) @@ -77,26 +75,25 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest { object.setPayload(TEST_STRING); object.getMetadata().setContentType(MediaType.TEXT_PLAIN); object.getMetadata().setSize(new Long(TEST_STRING.length())); - // NOTE all metadata in jclouds comes out as lowercase, in an effort to normalize the + // NOTE all metadata in jclouds comes out as lowercase, in an effort to + // normalize the // providers. object.getMetadata().getUserMetadata().put("Adrian", "powderpuff"); - object.getMetadata() - .setContentMD5(new JCEEncryptionService().md5(toInputStream(TEST_STRING))); + object.getMetadata().setContentMD5(encryptionService.md5(toInputStream(TEST_STRING))); String containerName = getContainerName(); try { addBlobToContainer(containerName, object); validateContent(containerName, key); PageSet container = context.getBlobStore().list(containerName, - maxResults(1).withDetails()); + maxResults(1).withDetails()); BlobMetadata metadata = BlobMetadata.class.cast(get(container, 0)); assert metadata.getContentType().startsWith("text/plain") : metadata.getContentType(); assertEquals(metadata.getSize(), new Long(TEST_STRING.length())); assertEquals(metadata.getUserMetadata().get("adrian"), "powderpuff"); - assertEquals(metadata.getContentMD5(), new JCEEncryptionService() - .md5(toInputStream(TEST_STRING))); + assertEquals(metadata.getContentMD5(), encryptionService.md5(toInputStream(TEST_STRING))); } finally { returnContainer(containerName); } @@ -119,8 +116,7 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest { String containerName = getContainerName(); try { addAlphabetUnderRoot(containerName); - PageSet container = context.getBlobStore().list(containerName, - maxResults(1)); + PageSet container = context.getBlobStore().list(containerName, maxResults(1)); assert container.getNextMarker() != null; assertEquals(container.size(), 1); @@ -128,8 +124,8 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest { container = context.getBlobStore().list(containerName, afterMarker(marker)); assertEquals(container.getNextMarker(), null); - assert container.size() == 25 : String.format("size should have been 25, but was %d: %s", - container.size(), container); + assert container.size() == 25 : String.format("size should have been 25, but was %d: %s", container.size(), + container); assert container.getNextMarker() == null; } finally { @@ -138,8 +134,7 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest { } @Test(groups = { "integration", "live" }) - public void testListRootUsesDelimiter() throws InterruptedException, - UnsupportedEncodingException { + public void testListRootUsesDelimiter() throws InterruptedException, UnsupportedEncodingException { String containerName = getContainerName(); try { String prefix = "rootdelimeter"; @@ -239,8 +234,7 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest { addTenObjectsUnderPrefix(containerName, prefix); add15UnderRoot(containerName); - PageSet container = context.getBlobStore().list(containerName, - inDirectory(prefix)); + PageSet container = context.getBlobStore().list(containerName, inDirectory(prefix)); assert container.getNextMarker() == null; assertEquals(container.size(), 10); } finally { @@ -250,13 +244,11 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest { } @Test(groups = { "integration", "live" }) - public void testListContainerMaxResults() throws InterruptedException, - UnsupportedEncodingException { + public void testListContainerMaxResults() throws InterruptedException, UnsupportedEncodingException { String containerName = getContainerName(); try { addAlphabetUnderRoot(containerName); - PageSet container = context.getBlobStore().list(containerName, - maxResults(5)); + PageSet container = context.getBlobStore().list(containerName, maxResults(5)); assertEquals(container.size(), 5); assert container.getNextMarker() != null; } finally { @@ -302,8 +294,8 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest { assertConsistencyAware(new Runnable() { public void run() { try { - assert !context.getBlobStore().containerExists(containerName) : "container " - + containerName + " still exists"; + assert !context.getBlobStore().containerExists(containerName) : "container " + containerName + + " still exists"; } catch (Exception e) { propagateIfPossible(e); } @@ -312,8 +304,8 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest { } @Test(groups = { "integration", "live" }) - public void testListContainer() throws InterruptedException, ExecutionException, - TimeoutException, UnsupportedEncodingException { + public void testListContainer() throws InterruptedException, ExecutionException, TimeoutException, + UnsupportedEncodingException { String containerName = getContainerName(); try { add15UnderRoot(containerName); @@ -341,8 +333,7 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest { } } - protected void addTenObjectsUnderPrefix(String containerName, String prefix) - throws InterruptedException { + protected void addTenObjectsUnderPrefix(String containerName, String prefix) throws InterruptedException { for (int i = 0; i < 10; i++) { Blob blob = context.getBlobStore().newBlob(prefix + "/" + i); blob.setPayload(i + "content"); diff --git a/chef/pom.xml b/chef/pom.xml index 0201872d8d..628b0ad566 100644 --- a/chef/pom.xml +++ b/chef/pom.xml @@ -1,102 +1,92 @@ - + + 4.0.0 + + org.jclouds + jclouds-project + 1.0-SNAPSHOT + ../project/pom.xml + + org.jclouds + jclouds-chef + jclouds Chef core + jclouds components to access Chef - http://www.apache.org/licenses/LICENSE-2.0.html + + scm:svn:http://jclouds.googlecode.com/svn/trunk/chef + scm:svn:https://jclouds.googlecode.com/svn/trunk/chef + http://jclouds.googlecode.com/svn/trunk/chef + - 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. - ==================================================================== - --> - - 4.0.0 - - org.jclouds - jclouds-project - 1.0-SNAPSHOT - ../project/pom.xml - - org.jclouds - jclouds-chef - jclouds Chef core - jclouds components to access Chef + + + + jclouds-googlecode-deploy + http://jclouds.googlecode.com/svn/repo + + + jclouds-rimu-snapshots-nexus + http://jclouds.rimuhosting.com:8081/nexus/content/repositories/snapshots + + true + + + - - scm:svn:http://jclouds.googlecode.com/svn/trunk/chef - scm:svn:https://jclouds.googlecode.com/svn/trunk/chef - http://jclouds.googlecode.com/svn/trunk/chef - - - - - - jclouds-googlecode-deploy - http://jclouds.googlecode.com/svn/repo - - - jclouds-rimu-snapshots-nexus - http://jclouds.rimuhosting.com:8081/nexus/content/repositories/snapshots - - true - - - - - - chef-validator - /etc/chef/validation.pem - http://localhost:4000 - ${jclouds.chef.identity} - ${jclouds.chef.rsa-key} - ${jclouds.chef.endpoint} - + + chef-validator + /etc/chef/validation.pem + http://localhost:4000 + ${jclouds.chef.identity} + ${jclouds.chef.rsa-key} + ${jclouds.chef.endpoint} + - - - org.bouncycastle - bcprov-jdk15 - 1.44 - - - ${project.groupId} - jclouds-core - ${project.version} - - - ${project.groupId} - jclouds-core - ${project.version} - test-jar - test - - - log4j - log4j - 1.2.14 - test - - - ${project.groupId} - jclouds-log4j - ${project.version} - test - - + + + ${project.groupId} + jclouds-core + ${project.version} + + + ${project.groupId} + jclouds-core + ${project.version} + test-jar + test + + + log4j + log4j + 1.2.14 + test + + + ${project.groupId} + jclouds-log4j + ${project.version} + test + + diff --git a/chef/src/main/java/org/jclouds/chef/config/BaseChefRestClientModule.java b/chef/src/main/java/org/jclouds/chef/config/BaseChefRestClientModule.java index b4ff8634d9..2ffd825c7a 100644 --- a/chef/src/main/java/org/jclouds/chef/config/BaseChefRestClientModule.java +++ b/chef/src/main/java/org/jclouds/chef/config/BaseChefRestClientModule.java @@ -44,24 +44,22 @@ package org.jclouds.chef.config; import static org.jclouds.Constants.PROPERTY_CREDENTIAL; import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; -import java.io.IOException; -import java.io.StringReader; -import java.security.KeyPair; +import java.io.UnsupportedEncodingException; import java.security.PrivateKey; -import java.security.Security; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.inject.Named; import javax.inject.Singleton; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.openssl.PEMReader; +import org.jclouds.chef.handlers.ChefClientErrorRetryHandler; import org.jclouds.chef.handlers.ChefErrorHandler; import org.jclouds.concurrent.ExpirableSupplier; import org.jclouds.date.DateService; import org.jclouds.date.TimeStamp; +import org.jclouds.encryption.EncryptionService; import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.RequiresHttp; import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.Redirection; @@ -88,7 +86,7 @@ public class BaseChefRestClientModule extends RestClientModule { } protected BaseChefRestClientModule(Class syncClientType, Class asyncClientType, - Map, Class> delegates) { + Map, Class> delegates) { super(syncClientType, asyncClientType, delegates); } @@ -103,8 +101,7 @@ public class BaseChefRestClientModule extends RestClientModule { */ @Provides @TimeStamp - Supplier provideTimeStampCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds, - final DateService dateService) { + Supplier provideTimeStampCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds, final DateService dateService) { return new ExpirableSupplier(new Supplier() { public String get() { return dateService.iso8601SecondsDateFormat(); @@ -114,11 +111,9 @@ public class BaseChefRestClientModule extends RestClientModule { @Provides @Singleton - public PrivateKey provideKey(@Named(PROPERTY_CREDENTIAL) String key) throws IOException { - // TODO do this without adding a provider - Security.addProvider(new BouncyCastleProvider()); - KeyPair pair = KeyPair.class.cast(new PEMReader(new StringReader(key)).readObject()); - return pair.getPrivate(); + public PrivateKey provideKey(EncryptionService encryptionService, @Named(PROPERTY_CREDENTIAL) String pem) + throws UnsupportedEncodingException { + return encryptionService.readPrivateKeyFromPEM(pem.getBytes("UTF-8")); } @Override @@ -128,6 +123,11 @@ public class BaseChefRestClientModule extends RestClientModule { bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ChefErrorHandler.class); } + @Override + protected void bindRetryHandlers() { + bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(ChefClientErrorRetryHandler.class); + } + @Override protected void configure() { bind(DateAdapter.class).to(Iso8601DateAdapter.class); diff --git a/chef/src/main/java/org/jclouds/chef/handlers/ChefClientErrorRetryHandler.java b/chef/src/main/java/org/jclouds/chef/handlers/ChefClientErrorRetryHandler.java new file mode 100644 index 0000000000..62093e0bf6 --- /dev/null +++ b/chef/src/main/java/org/jclouds/chef/handlers/ChefClientErrorRetryHandler.java @@ -0,0 +1,72 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed 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.chef.handlers; + +import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream; + +import javax.annotation.Resource; +import javax.inject.Named; + +import org.jclouds.Constants; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpRetryHandler; +import org.jclouds.http.handlers.BackoffLimitedRetryHandler; +import org.jclouds.logging.Logger; + +import com.google.inject.Inject; + +/** + * Allow for eventual consistency on sandbox requests. + * + * @author Adrian Cole + */ +public class ChefClientErrorRetryHandler implements HttpRetryHandler { + + @Inject(optional = true) + @Named(Constants.PROPERTY_MAX_RETRIES) + private int retryCountLimit = 5; + + @Resource + protected Logger logger = Logger.NULL; + + private final BackoffLimitedRetryHandler backoffLimitedRetryHandler; + + @Inject + ChefClientErrorRetryHandler(BackoffLimitedRetryHandler backoffLimitedRetryHandler) { + this.backoffLimitedRetryHandler = backoffLimitedRetryHandler; + } + + public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { + if (command.getFailureCount() > retryCountLimit) + return false; + if (response.getStatusCode() == 400 && command.getRequest().getMethod().equals("PUT") + && command.getRequest().getEndpoint().getPath().indexOf("sandboxes") != -1) { + if (response.getPayload() != null) { + String error = new String(closeClientButKeepContentStream(response)); + if (error != null && error.indexOf("was not uploaded") != -1) { + return backoffLimitedRetryHandler.shouldRetryRequest(command, response); + } + } + } + return false; + } + +} diff --git a/chef/src/test/java/org/jclouds/chef/ChefClientLiveTest.java b/chef/src/test/java/org/jclouds/chef/ChefClientLiveTest.java index 6728d33cb1..9d9e9d53f6 100644 --- a/chef/src/test/java/org/jclouds/chef/ChefClientLiveTest.java +++ b/chef/src/test/java/org/jclouds/chef/ChefClientLiveTest.java @@ -106,6 +106,7 @@ public class ChefClientLiveTest { // define the file you want in the cookbook FilePayload content = Payloads.newFilePayload(new File(System.getProperty("user.dir"), "pom.xml")); + content.setContentType("application/x-binary"); // get an md5 so that you can see if the server already has it or not adminConnection.utils().encryption().generateMD5BufferingIfNotRepeatable(content); @@ -126,7 +127,6 @@ public class ChefClientLiveTest { adminConnection.utils().http().put(status.getUrl(), content); } - // if we were able to get here, close the sandbox adminConnection.getApi().commitSandbox(site.getSandboxId(), true); } catch (RuntimeException e) { diff --git a/chef/src/test/java/org/jclouds/chef/filters/SignedHeaderAuthTest.java b/chef/src/test/java/org/jclouds/chef/filters/SignedHeaderAuthTest.java index adc345de0d..9b11c623c0 100644 --- a/chef/src/test/java/org/jclouds/chef/filters/SignedHeaderAuthTest.java +++ b/chef/src/test/java/org/jclouds/chef/filters/SignedHeaderAuthTest.java @@ -26,19 +26,14 @@ package org.jclouds.chef.filters; import static org.testng.Assert.assertEquals; import java.io.IOException; -import java.io.StringReader; import java.net.URI; -import java.security.KeyPair; import java.security.PrivateKey; -import java.security.Security; import java.util.Properties; import javax.inject.Provider; import javax.ws.rs.HttpMethod; import javax.ws.rs.core.HttpHeaders; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.openssl.PEMReader; import org.jclouds.encryption.EncryptionService; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpUtils; @@ -82,54 +77,42 @@ public class SignedHeaderAuthTest { public static final String X_OPS_CONTENT_HASH = "DFteJZPVv6WKdQmMqZUQUumUyRs="; public static final String[] X_OPS_AUTHORIZATION_LINES = new String[] { - "jVHrNniWzpbez/eGWjFnO6lINRIuKOg40ZTIQudcFe47Z9e/HvrszfVXlKG4", - "NMzYZgyooSvU85qkIUmKuCqgG2AIlvYa2Q/2ctrMhoaHhLOCWWoqYNMaEqPc", - "3tKHE+CfvP+WuPdWk4jv4wpIkAz6ZLxToxcGhXmZbXpk56YTmqgBW2cbbw4O", - "IWPZDHSiPcw//AYNgW1CCDptt+UFuaFYbtqZegcBd2n/jzcWODA7zL4KWEUy", - "9q4rlh/+1tBReg60QdsmDRsw/cdO1GZrKtuCwbuD4+nbRdVBKv72rqHX9cu0", - "utju9jzczCyB+sSAQWrxSsXB/b8vV2qs0l4VD2ML+w==" }; + "jVHrNniWzpbez/eGWjFnO6lINRIuKOg40ZTIQudcFe47Z9e/HvrszfVXlKG4", + "NMzYZgyooSvU85qkIUmKuCqgG2AIlvYa2Q/2ctrMhoaHhLOCWWoqYNMaEqPc", + "3tKHE+CfvP+WuPdWk4jv4wpIkAz6ZLxToxcGhXmZbXpk56YTmqgBW2cbbw4O", + "IWPZDHSiPcw//AYNgW1CCDptt+UFuaFYbtqZegcBd2n/jzcWODA7zL4KWEUy", + "9q4rlh/+1tBReg60QdsmDRsw/cdO1GZrKtuCwbuD4+nbRdVBKv72rqHX9cu0", "utju9jzczCyB+sSAQWrxSsXB/b8vV2qs0l4VD2ML+w==" }; // We expect Mixlib::Authentication::SignedHeaderAuth//sign to return this // if passed the BODY above. - public static final Multimap EXPECTED_SIGN_RESULT = ImmutableMultimap - . builder().put("X-Ops-Content-Hash", X_OPS_CONTENT_HASH).put( - "X-Ops-Userid", USER_ID).put("X-Ops-Sign", "version=1.0").put( - "X-Ops-Authorization-1", X_OPS_AUTHORIZATION_LINES[0]).put( - "X-Ops-Authorization-2", X_OPS_AUTHORIZATION_LINES[1]).put( - "X-Ops-Authorization-3", X_OPS_AUTHORIZATION_LINES[2]).put( - "X-Ops-Authorization-4", X_OPS_AUTHORIZATION_LINES[3]).put( - "X-Ops-Authorization-5", X_OPS_AUTHORIZATION_LINES[4]).put( - "X-Ops-Authorization-6", X_OPS_AUTHORIZATION_LINES[5]).put("X-Ops-Timestamp", - TIMESTAMP_ISO8601).build(); + public static final Multimap EXPECTED_SIGN_RESULT = ImmutableMultimap. builder() + .put("X-Ops-Content-Hash", X_OPS_CONTENT_HASH).put("X-Ops-Userid", USER_ID).put("X-Ops-Sign", "version=1.0") + .put("X-Ops-Authorization-1", X_OPS_AUTHORIZATION_LINES[0]).put("X-Ops-Authorization-2", + X_OPS_AUTHORIZATION_LINES[1]).put("X-Ops-Authorization-3", X_OPS_AUTHORIZATION_LINES[2]).put( + "X-Ops-Authorization-4", X_OPS_AUTHORIZATION_LINES[3]).put("X-Ops-Authorization-5", + X_OPS_AUTHORIZATION_LINES[4]).put("X-Ops-Authorization-6", X_OPS_AUTHORIZATION_LINES[5]).put( + "X-Ops-Timestamp", TIMESTAMP_ISO8601).build(); // Content hash for empty string public static final String X_OPS_CONTENT_HASH_EMPTY = "2jmj7l5rSw0yVb/vlWAYkK/YBwk="; public static final Multimap EXPECTED_SIGN_RESULT_EMPTY = ImmutableMultimap - . builder().put("X-Ops-Content-Hash", X_OPS_CONTENT_HASH_EMPTY).put( - "X-Ops-Userid", USER_ID).put("X-Ops-Sign", "version=1.0").put( - "X-Ops-Authorization-1", - "N6U75kopDK64cEFqrB6vw+PnubnXr0w5LQeXnIGNGLRP2LvifwIeisk7QxEx").put( - "X-Ops-Authorization-2", - "mtpQOWAw8HvnWErjzuk9AvUsqVmWpv14ficvkaD79qsPMvbje+aLcIrCGT1P").put( - "X-Ops-Authorization-3", - "3d2uvf4w7iqwzrIscPnkxLR6o6pymR90gvJXDPzV7Le0jbfD8kmZ8AAK0sGG").put( - "X-Ops-Authorization-4", - "09F1ftW80bLatJTA66Cw2wBz261r6x/abZhIKFJFDWLzyQGJ8ZNOkUrDDtgI").put( - "X-Ops-Authorization-5", - "svLVXpOJKZZfKunsElpWjjsyNt3k8vpI1Y4ANO8Eg2bmeCPeEK+YriGm5fbC").put( - "X-Ops-Authorization-6", "DzWNPylHJqMeGKVYwGQKpg62QDfe5yXh3wZLiQcXow==").put( - "X-Ops-Timestamp", TIMESTAMP_ISO8601).build(); + . builder().put("X-Ops-Content-Hash", X_OPS_CONTENT_HASH_EMPTY).put("X-Ops-Userid", USER_ID) + .put("X-Ops-Sign", "version=1.0").put("X-Ops-Authorization-1", + "N6U75kopDK64cEFqrB6vw+PnubnXr0w5LQeXnIGNGLRP2LvifwIeisk7QxEx").put("X-Ops-Authorization-2", + "mtpQOWAw8HvnWErjzuk9AvUsqVmWpv14ficvkaD79qsPMvbje+aLcIrCGT1P").put("X-Ops-Authorization-3", + "3d2uvf4w7iqwzrIscPnkxLR6o6pymR90gvJXDPzV7Le0jbfD8kmZ8AAK0sGG").put("X-Ops-Authorization-4", + "09F1ftW80bLatJTA66Cw2wBz261r6x/abZhIKFJFDWLzyQGJ8ZNOkUrDDtgI").put("X-Ops-Authorization-5", + "svLVXpOJKZZfKunsElpWjjsyNt3k8vpI1Y4ANO8Eg2bmeCPeEK+YriGm5fbC").put("X-Ops-Authorization-6", + "DzWNPylHJqMeGKVYwGQKpg62QDfe5yXh3wZLiQcXow==").put("X-Ops-Timestamp", TIMESTAMP_ISO8601).build(); public static String PUBLIC_KEY; public static String PRIVATE_KEY; static { try { - PUBLIC_KEY = Utils.toStringAndClose(SignedHeaderAuthTest.class - .getResourceAsStream("/pubkey.txt")); + PUBLIC_KEY = Utils.toStringAndClose(SignedHeaderAuthTest.class.getResourceAsStream("/pubkey.txt")); - PRIVATE_KEY = Utils.toStringAndClose(SignedHeaderAuthTest.class - .getResourceAsStream("/privkey.txt")); + PRIVATE_KEY = Utils.toStringAndClose(SignedHeaderAuthTest.class.getResourceAsStream("/privkey.txt")); } catch (IOException e) { Throwables.propagate(e); } @@ -152,20 +135,17 @@ public class SignedHeaderAuthTest { HttpRequest request = new HttpRequest(HttpMethod.POST, host); request.setPayload(BODY); - String expected_string_to_sign = new StringBuilder().append("Method:POST").append("\n") - .append("Hashed Path:").append(HASHED_CANONICAL_PATH).append("\n").append( - "X-Ops-Content-Hash:").append(HASHED_BODY).append("\n").append( - "X-Ops-Timestamp:").append(TIMESTAMP_ISO8601).append("\n").append( - "X-Ops-UserId:").append(USER_ID).toString(); + String expected_string_to_sign = new StringBuilder().append("Method:POST").append("\n").append("Hashed Path:") + .append(HASHED_CANONICAL_PATH).append("\n").append("X-Ops-Content-Hash:").append(HASHED_BODY).append("\n") + .append("X-Ops-Timestamp:").append(TIMESTAMP_ISO8601).append("\n").append("X-Ops-UserId:").append(USER_ID) + .toString(); - assertEquals(signing_obj.createStringToSign("POST", HASHED_CANONICAL_PATH, HASHED_BODY, - TIMESTAMP_ISO8601), expected_string_to_sign); - assertEquals(signing_obj.sign(expected_string_to_sign), Joiner.on("").join( - X_OPS_AUTHORIZATION_LINES)); + assertEquals(signing_obj.createStringToSign("POST", HASHED_CANONICAL_PATH, HASHED_BODY, TIMESTAMP_ISO8601), + expected_string_to_sign); + assertEquals(signing_obj.sign(expected_string_to_sign), Joiner.on("").join(X_OPS_AUTHORIZATION_LINES)); signing_obj.filter(request); - Multimap headersWithoutContentLength = LinkedHashMultimap.create(request - .getHeaders()); + Multimap headersWithoutContentLength = LinkedHashMultimap.create(request.getHeaders()); headersWithoutContentLength.removeAll(HttpHeaders.CONTENT_LENGTH); assertEquals(headersWithoutContentLength.values(), EXPECTED_SIGN_RESULT.values()); } @@ -177,8 +157,7 @@ public class SignedHeaderAuthTest { HttpRequest request = new HttpRequest(HttpMethod.DELETE, host); signing_obj.filter(request); - Multimap headersWithoutContentLength = LinkedHashMultimap.create(request - .getHeaders()); + Multimap headersWithoutContentLength = LinkedHashMultimap.create(request.getHeaders()); assertEquals(headersWithoutContentLength.entries(), EXPECTED_SIGN_RESULT_EMPTY.entries()); } @@ -196,12 +175,6 @@ public class SignedHeaderAuthTest { private SignedHeaderAuth signing_obj; private EncryptionService encryptionService; - @Test(enabled = false) - void canParseKeyFromCreateClient() throws IOException { - String key = "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA50Iwgq8OIfm5vY9Gwfb6UBt17D7V4djyFSLJ1AbCU/o8Zlrr\nW73JqaK5dC3IO6Dcu+/qPYGtBUWvhFAXrsFOooz0mTod/LtBN1YVurJ60goJrR6w\nKhUYC9H45OW/qcdIM7kdDwiyMZfbHqW6fo0xPqjvgxtZoI+v7pgThacOG6pw7PO6\nGgnJa3MGK3xEbzlI6+EBJWG3EiwexguwOpTD4a4TDIAqKrlVDPeUpU7rFbsBPRS8\nkypR3lU58+WRz/zi9fiH/Sy2X+ChefyZg14HiutJjxc8zJsazF3eDxyLGPQmhv3Mso\nA0wbjGusbe6hPdDkzh/B2KO9u96QCdlGu/rc6QIDAQABAoIBAA/7OgD9+fsNF/Hq\nodgrqja4/xg5a2x1Ip2lTs9RPEKza1Mje1pWrkYD0c8ejtTYFAkE1mozuPJBU5TQ\nOCLChx2iohCovIPHqQUa9Nt3FBfJy8tj8Ian+IZwl0OyQOGJvQqeA00Tq8TTmrfu\negne1gVfhVXJIROAeocBiW/WEJqGti0OE5zQQMld3cJ5viTdEsaWYCu2HaEoblKB\nH6KfRGM2N3L3KjKFGtEg+cX1UdaMlzmp+O5/yvjBykZy6cuUOIsgz2e5nQV4hYEq\ntJ/+6E0QVTXfnVZi4IxKlkVMhyonqOxAOKGG+dWeWh3DqPJFzjmp3kcbRN9E3u+2\nqKU5gpECgYEA+a/i5z2jFCJ8rMpoCPPxm2eiIYZVs3LE33WU5FNNieBRC+KqO06h\nMB3rQ3k8KJDNJYWD5UwIrgjCD5mgkmcSDI6SbOn6PA1Mtw6qZlbeg17V9L9ryXxt\nSfC5AC+qVWd6unrLh0LgkvLS8rgG4GjLZY0HDDMrJWodcc+uWVk3Mo0CgYEA7RsG\nC9gOcHWi6WJ2uEDvLj4IkSkB4IFipEVcKl7VVDSnUgxaBZm3o0DLYDYhIOw7XcQL\n6vpxbRZdlApGyu1ahfMbk3+quFNMQuGxZcv9EhHz7ASnXK6mlrWkJzCGjLz6/MdI\nU0VGbtkBtOY/GaLXdTkQksWowVNoedISfQV9as0CgYEA0Tj1JVecw05yskeZDYd8\nOQCJ9xWd0pSlK6pXbUvweUwiHZd9ldy5bJxle1CnfEZ54KsUbptb2pk0I+ZTitob\nYbJGOEWHjbKHSg1b9A1uvx5EoqWUKG2/FmpEW0eVr6LaUFB9I4aCsCARa5mRCZJG\nfX3DHhHyYZOdwLSKIAyGGDECgYALEwkMQpIiFIyAZBXxcy74tPMHfKfWyZRG4ep1\nHCrQnQj3nxYRTuWx3VPicYTImeAH+CEqX3ouwy2pvXUjA0UIHpu6HutlYpacRRhZ\nDdcLIgWHj4wVmx6yyVcacXzHVAhRCCnLod+xS7d1sI9f7igsFHc+s7a3GOM3VWWB\nq2D5PQKBgQDY9eSb5pc5EYbPy0a/wKFLMNCVLXlDT8jRSC2UnhmcHbhi1IdUbn1j\nR+SuUgrAVNAKzJRY9wmF6Zt0pJ2YLFX7L8HaGyfzkib8kli2sXFonlQ4d0dTdcJo\nVGR1jTxfZQicdPcDPOLPpQz/rP31ZqdHtfaegTOxHebX7W2E5QvPZg==\n-----END RSA PRIVATE KEY-----\n"; - KeyPair.class.cast(new PEMReader(new StringReader(key)).readObject()); - } - /** * before class, as we need to ensure that the filter is threadsafe. * @@ -211,28 +184,22 @@ public class SignedHeaderAuthTest { @BeforeClass protected void createFilter() throws IOException { - Injector injector = new RestContextFactory().createContextBuilder("chef", USER_ID, - PRIVATE_KEY, ImmutableSet. of(new MockModule(), new NullLoggingModule()), - new Properties()).buildInjector(); + Injector injector = new RestContextFactory().createContextBuilder("chef", USER_ID, PRIVATE_KEY, + ImmutableSet. of(new MockModule(), new NullLoggingModule()), new Properties()).buildInjector(); encryptionService = injector.getInstance(EncryptionService.class); HttpUtils utils = injector.getInstance(HttpUtils.class); - Security.addProvider(new BouncyCastleProvider()); + PrivateKey privateKey = injector.getInstance(PrivateKey.class); - KeyPair pair = KeyPair.class.cast(new PEMReader(new StringReader(PRIVATE_KEY)).readObject()); + signing_obj = new SignedHeaderAuth(new SignatureWire(), USER_ID, privateKey, new Provider() { - PrivateKey privateKey = pair.getPrivate(); + @Override + public String get() { + return TIMESTAMP_ISO8601; + } - signing_obj = new SignedHeaderAuth(new SignatureWire(), USER_ID, privateKey, - new Provider() { - - @Override - public String get() { - return TIMESTAMP_ISO8601; - } - - }, encryptionService, utils); + }, encryptionService, utils); } } \ No newline at end of file diff --git a/chef/src/test/java/org/jclouds/chef/handlers/ChefClientErrorRetryHandlerTest.java b/chef/src/test/java/org/jclouds/chef/handlers/ChefClientErrorRetryHandlerTest.java new file mode 100644 index 0000000000..a91a0438e2 --- /dev/null +++ b/chef/src/test/java/org/jclouds/chef/handlers/ChefClientErrorRetryHandlerTest.java @@ -0,0 +1,101 @@ +package org.jclouds.chef.handlers; + +import static org.easymock.EasyMock.expect; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.easymock.classextension.EasyMock.verify; + +import java.net.URI; + +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.handlers.BackoffLimitedRetryHandler; +import org.jclouds.io.Payloads; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code ChefClientErrorRetryHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "chef.ChefClientErrorRetryHandlerTest") +public class ChefClientErrorRetryHandlerTest { + @Test + public void test401DoesNotRetry() { + + HttpCommand command = createMock(HttpCommand.class); + HttpResponse response = createMock(HttpResponse.class); + BackoffLimitedRetryHandler retry = createMock(BackoffLimitedRetryHandler.class); + + expect(command.getFailureCount()).andReturn(0); + expect(response.getStatusCode()).andReturn(401).atLeastOnce(); + + replay(response); + replay(retry); + replay(command); + + ChefClientErrorRetryHandler handler = new ChefClientErrorRetryHandler(retry); + + assert !handler.shouldRetryRequest(command, response); + + verify(retry); + verify(command); + verify(response); + + } + + @Test + public void test400DoesNotRetry() { + + HttpCommand command = createMock(HttpCommand.class); + HttpResponse response = createMock(HttpResponse.class); + BackoffLimitedRetryHandler retry = createMock(BackoffLimitedRetryHandler.class); + + expect(command.getFailureCount()).andReturn(0); + expect(response.getStatusCode()).andReturn(401).atLeastOnce(); + + replay(response); + replay(retry); + replay(command); + + ChefClientErrorRetryHandler handler = new ChefClientErrorRetryHandler(retry); + + assert !handler.shouldRetryRequest(command, response); + + verify(retry); + verify(command); + verify(response); + + } + + @Test + public void testRetryOn400PutSandbox() { + + HttpCommand command = createMock(HttpCommand.class); + BackoffLimitedRetryHandler retry = createMock(BackoffLimitedRetryHandler.class); + + HttpRequest request = new HttpRequest("PUT", URI + .create("https://api.opscode.com/organizations/jclouds/sandboxes/bfd68d4052f44053b2e593a33b5e1cd5")); + HttpResponse response = new HttpResponse( + 400, + "400 Bad Request", + Payloads + .newStringPayload("{\"error\":[\"Cannot update sandbox bfd68d4052f44053b2e593a33b5e1cd5: checksum 9b7c23369f4b576451216c39f214af6c was not uploaded\"]}")); + + expect(command.getFailureCount()).andReturn(0); + expect(command.getRequest()).andReturn(request).atLeastOnce(); + expect(retry.shouldRetryRequest(command, response)).andReturn(true); + + replay(retry); + replay(command); + + ChefClientErrorRetryHandler handler = new ChefClientErrorRetryHandler(retry); + + assert handler.shouldRetryRequest(command, response); + + verify(retry); + verify(command); + + } +} diff --git a/core/pom.xml b/core/pom.xml index c4ff3aab1a..183612c760 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -45,9 +45,20 @@ gson http://google-gson.googlecode.com/svn/mavenrepo + + oauth + OAuth Repository + http://oauth.googlecode.com/svn/code/maven + + + net.oauth.core + oauth + 20100527 + + aopalliance aopalliance diff --git a/core/src/main/java/org/jclouds/encryption/EncryptionService.java b/core/src/main/java/org/jclouds/encryption/EncryptionService.java index 2e378eeefc..e444c8e171 100644 --- a/core/src/main/java/org/jclouds/encryption/EncryptionService.java +++ b/core/src/main/java/org/jclouds/encryption/EncryptionService.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.Key; +import java.security.PrivateKey; import org.jclouds.encryption.internal.JCEEncryptionService; import org.jclouds.http.PayloadEnclosing; @@ -73,6 +74,8 @@ public interface EncryptionService { MD5OutputStream md5OutputStream(OutputStream out); + PrivateKey readPrivateKeyFromPEM(byte [] pem); + public static abstract class MD5OutputStream extends FilterOutputStream { public MD5OutputStream(OutputStream out) { super(out); diff --git a/core/src/main/java/org/jclouds/encryption/internal/BaseEncryptionService.java b/core/src/main/java/org/jclouds/encryption/internal/BaseEncryptionService.java index 61ecc30e6f..bed6442bcd 100755 --- a/core/src/main/java/org/jclouds/encryption/internal/BaseEncryptionService.java +++ b/core/src/main/java/org/jclouds/encryption/internal/BaseEncryptionService.java @@ -21,30 +21,44 @@ package org.jclouds.encryption.internal; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.spec.KeySpec; +import java.security.spec.PKCS8EncodedKeySpec; import javax.annotation.Resource; +import net.oauth.signature.pem.PEMReader; +import net.oauth.signature.pem.PKCS1EncodedKeySpec; + import org.jclouds.encryption.EncryptionService; import org.jclouds.http.PayloadEnclosing; import org.jclouds.io.Payload; import org.jclouds.logging.Logger; +import com.google.common.base.Throwables; + /** * * @author Adrian Cole */ public abstract class BaseEncryptionService implements EncryptionService { - + @Resource protected Logger logger = Logger.NULL; - + protected static final int BUF_SIZE = 0x2000; // 8 + final byte[] HEX_CHAR_TABLE = { (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', + (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f' }; - final byte[] HEX_CHAR_TABLE = { (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', - (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', - (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f' }; + private final KeyFactory rsaKeyFactory; + + public BaseEncryptionService(KeyFactory rsaKeyFactory) { + this.rsaKeyFactory = rsaKeyFactory; + } @Override public String hex(byte[] raw) { @@ -90,7 +104,6 @@ public abstract class BaseEncryptionService implements EncryptionService { /** * {@inheritDoc} - * @ */ @Override public T generateMD5BufferingIfNotRepeatable(T payloadEnclosing) { @@ -100,4 +113,30 @@ public abstract class BaseEncryptionService implements EncryptionService { payloadEnclosing.setPayload(newPayload); return payloadEnclosing; } + + /** + * {@inheritDoc} + */ + @Override + public PrivateKey readPrivateKeyFromPEM(byte[] pem) { + PEMReader reader; + try { + reader = new PEMReader(pem); + + byte[] bytes = reader.getDerBytes(); + KeySpec keySpec; + + if (PEMReader.PRIVATE_PKCS1_MARKER.equals(reader.getBeginMarker())) { + keySpec = (new PKCS1EncodedKeySpec(bytes)).getKeySpec(); + } else if (PEMReader.PRIVATE_PKCS8_MARKER.equals(reader.getBeginMarker())) { + keySpec = new PKCS8EncodedKeySpec(bytes); + } else { + throw new IOException("Invalid PEM file: Unknown marker " + "for private key " + reader.getBeginMarker()); + } + return rsaKeyFactory.generatePrivate(keySpec); + } catch (Exception e) { + Throwables.propagate(e); + return null; + } + } } diff --git a/core/src/main/java/org/jclouds/encryption/internal/JCEEncryptionService.java b/core/src/main/java/org/jclouds/encryption/internal/JCEEncryptionService.java index a21f450e54..7d4943222d 100644 --- a/core/src/main/java/org/jclouds/encryption/internal/JCEEncryptionService.java +++ b/core/src/main/java/org/jclouds/encryption/internal/JCEEncryptionService.java @@ -28,6 +28,7 @@ import java.io.OutputStream; import java.security.DigestOutputStream; import java.security.InvalidKeyException; import java.security.Key; +import java.security.KeyFactory; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -43,6 +44,14 @@ import org.jclouds.io.payloads.ByteArrayPayload; */ public class JCEEncryptionService extends BaseEncryptionService { + public JCEEncryptionService(KeyFactory rsaKeyFactory) { + super(rsaKeyFactory); + } + + public JCEEncryptionService() throws NoSuchAlgorithmException { + super(KeyFactory.getInstance("RSA")); + } + @Override public byte[] hmacSha256(String toEncode, byte[] key) { return hmac(toEncode, key, "HmacSHA256"); diff --git a/core/src/test/java/org/jclouds/http/BaseJettyTest.java b/core/src/test/java/org/jclouds/http/BaseJettyTest.java index ade3530750..051cf5c491 100644 --- a/core/src/test/java/org/jclouds/http/BaseJettyTest.java +++ b/core/src/test/java/org/jclouds/http/BaseJettyTest.java @@ -24,6 +24,7 @@ import static org.jclouds.rest.RestContextFactory.createContextBuilder; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.security.NoSuchAlgorithmException; import java.util.Map; import java.util.Properties; import java.util.concurrent.atomic.AtomicInteger; @@ -85,12 +86,11 @@ public abstract class BaseJettyTest { encryptionService = Guice.createInjector().getInstance(EncryptionService.class); - md5 = encryptionService - .base64(encryptionService.md5(oneHundredOneConstitutions.getInput())); + md5 = encryptionService.base64(encryptionService.md5(oneHundredOneConstitutions.getInput())); Handler server1Handler = new AbstractHandler() { - public void handle(String target, HttpServletRequest request, - HttpServletResponse response, int dispatch) throws IOException, ServletException { + public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) + throws IOException, ServletException { if (failIfNoContentLength(request, response)) { return; } else if (target.indexOf("redirect") > 0) { @@ -103,8 +103,7 @@ public abstract class BaseJettyTest { } else if (request.getMethod().equals("PUT")) { if (request.getContentLength() > 0) { response.setStatus(HttpServletResponse.SC_OK); - response.getWriter().println( - Utils.toStringAndClose(request.getInputStream()) + "PUT"); + response.getWriter().println(Utils.toStringAndClose(request.getInputStream()) + "PUT"); } else { response.sendError(500, "no content"); } @@ -116,8 +115,13 @@ public abstract class BaseJettyTest { if (request.getContentLength() > 0) { if (request.getHeader("Content-MD5") != null) { String expectedMd5 = request.getHeader("Content-MD5"); - String realMd5FromRequest = Base64.encodeBytes(new JCEEncryptionService() + String realMd5FromRequest; + try { + realMd5FromRequest = Base64.encodeBytes(new JCEEncryptionService() .md5(request.getInputStream())); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } boolean matched = expectedMd5.equals(realMd5FromRequest); if (matched) { response.setContentType("text/xml"); @@ -126,8 +130,7 @@ public abstract class BaseJettyTest { } } else { response.setStatus(HttpServletResponse.SC_OK); - response.getWriter().println( - Utils.toStringAndClose(request.getInputStream()) + "POST"); + response.getWriter().println(Utils.toStringAndClose(request.getInputStream()) + "POST"); } } else { handleAction(request, response); @@ -140,7 +143,8 @@ public abstract class BaseJettyTest { response.getWriter().println("test"); } else if (request.getMethod().equals("HEAD")) { /* - * NOTE: by HTML specification, HEAD response MUST NOT include a body + * NOTE: by HTML specification, HEAD response MUST NOT include a + * body */ response.setContentType("text/xml"); response.setStatus(HttpServletResponse.SC_OK); @@ -161,20 +165,24 @@ public abstract class BaseJettyTest { server.start(); Handler server2Handler = new AbstractHandler() { - public void handle(String target, HttpServletRequest request, - HttpServletResponse response, int dispatch) throws IOException, ServletException { + public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) + throws IOException, ServletException { if (request.getMethod().equals("PUT")) { if (request.getContentLength() > 0) { response.setStatus(HttpServletResponse.SC_OK); - response.getWriter().println( - Utils.toStringAndClose(request.getInputStream()) + "PUTREDIRECT"); + response.getWriter().println(Utils.toStringAndClose(request.getInputStream()) + "PUTREDIRECT"); } } else if (request.getMethod().equals("POST")) { if (request.getContentLength() > 0) { if (request.getHeader("Content-MD5") != null) { String expectedMd5 = request.getHeader("Content-MD5"); - String realMd5FromRequest = Base64.encodeBytes(new JCEEncryptionService() + String realMd5FromRequest; + try { + realMd5FromRequest = Base64.encodeBytes(new JCEEncryptionService() .md5(request.getInputStream())); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } boolean matched = expectedMd5.equals(realMd5FromRequest); if (matched) { response.setContentType("text/xml"); @@ -183,15 +191,15 @@ public abstract class BaseJettyTest { } } else { response.setStatus(HttpServletResponse.SC_OK); - response.getWriter().println( - Utils.toStringAndClose(request.getInputStream()) + "POST"); + response.getWriter().println(Utils.toStringAndClose(request.getInputStream()) + "POST"); } } else { handleAction(request, response); } } else if (request.getMethod().equals("HEAD")) { /* - * NOTE: by HTML specification, HEAD response MUST NOT include a body + * NOTE: by HTML specification, HEAD response MUST NOT include a + * body */ response.setContentType("text/xml"); response.setStatus(HttpServletResponse.SC_OK); @@ -220,9 +228,8 @@ public abstract class BaseJettyTest { @SuppressWarnings("unchecked") public static InputSupplier getTestDataSupplier() throws IOException { byte[] oneConstitution = ByteStreams.toByteArray(new GZIPInputStream(BaseJettyTest.class - .getResourceAsStream("/const.txt.gz"))); - InputSupplier constitutionSupplier = ByteStreams - .newInputStreamSupplier(oneConstitution); + .getResourceAsStream("/const.txt.gz"))); + InputSupplier constitutionSupplier = ByteStreams.newInputStreamSupplier(oneConstitution); InputSupplier temp = ByteStreams.join(constitutionSupplier); @@ -232,15 +239,14 @@ public abstract class BaseJettyTest { return temp; } - public static RestContextBuilder newBuilder( - int testPort, Properties properties, Module... connectionModules) { + public static RestContextBuilder newBuilder(int testPort, + Properties properties, Module... connectionModules) { - ContextSpec contextSpec = contextSpec( - "test", "http://localhost:" + testPort, "1", "identity", null, - IntegrationTestClient.class, IntegrationTestAsyncClient.class); + ContextSpec contextSpec = contextSpec("test", + "http://localhost:" + testPort, "1", "identity", null, IntegrationTestClient.class, + IntegrationTestAsyncClient.class); - return createContextBuilder(contextSpec, ImmutableSet. copyOf(connectionModules), - properties); + return createContextBuilder(contextSpec, ImmutableSet. copyOf(connectionModules), properties); } @AfterTest @@ -262,8 +268,7 @@ public abstract class BaseJettyTest { * @return * @throws IOException */ - protected boolean failEveryTenRequests(HttpServletRequest request, HttpServletResponse response) - throws IOException { + protected boolean failEveryTenRequests(HttpServletRequest request, HttpServletResponse response) throws IOException { if (cycle.incrementAndGet() % 10 == 0) { response.sendError(500); ((Request) request).setHandled(true); @@ -272,8 +277,8 @@ public abstract class BaseJettyTest { return false; } - protected boolean redirectEveryTwentyRequests(HttpServletRequest request, - HttpServletResponse response) throws IOException { + protected boolean redirectEveryTwentyRequests(HttpServletRequest request, HttpServletResponse response) + throws IOException { if (cycle.incrementAndGet() % 20 == 0) { response.sendRedirect("http://localhost:" + (testPort + 1) + "/"); ((Request) request).setHandled(true); @@ -282,8 +287,7 @@ public abstract class BaseJettyTest { return false; } - protected boolean failIfNoContentLength(HttpServletRequest request, HttpServletResponse response) - throws IOException { + protected boolean failIfNoContentLength(HttpServletRequest request, HttpServletResponse response) throws IOException { if (request.getHeader(HttpHeaders.CONTENT_LENGTH) == null) { response.sendError(500); ((Request) request).setHandled(true); @@ -292,8 +296,7 @@ public abstract class BaseJettyTest { return false; } - private void handleAction(HttpServletRequest request, HttpServletResponse response) - throws IOException { + private void handleAction(HttpServletRequest request, HttpServletResponse response) throws IOException { final Matcher matcher = actionPattern.matcher(request.getRequestURI()); boolean matchFound = matcher.find(); if (matchFound) { diff --git a/core/src/test/java/org/jclouds/http/filters/BasicAuthenticationTest.java b/core/src/test/java/org/jclouds/http/filters/BasicAuthenticationTest.java index 3864133eb0..5c064fb17d 100755 --- a/core/src/test/java/org/jclouds/http/filters/BasicAuthenticationTest.java +++ b/core/src/test/java/org/jclouds/http/filters/BasicAuthenticationTest.java @@ -22,6 +22,7 @@ import static org.testng.Assert.assertEquals; import java.io.UnsupportedEncodingException; import java.net.URI; +import java.security.NoSuchAlgorithmException; import javax.ws.rs.core.HttpHeaders; @@ -39,13 +40,11 @@ public class BasicAuthenticationTest { private static final String USER = "Aladdin"; private static final String PASSWORD = "open sesame"; - - public void testAuth() throws UnsupportedEncodingException { + public void testAuth() throws UnsupportedEncodingException, NoSuchAlgorithmException { BasicAuthentication filter = new BasicAuthentication(USER, PASSWORD, new JCEEncryptionService()); HttpRequest request = new HttpRequest("GET", URI.create("http://localhost")); filter.filter(request); - assertEquals(request.getFirstHeaderOrNull(HttpHeaders.AUTHORIZATION), - "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); + assertEquals(request.getFirstHeaderOrNull(HttpHeaders.AUTHORIZATION), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); } } \ No newline at end of file diff --git a/core/src/test/java/org/jclouds/http/internal/WireLiveTest.java b/core/src/test/java/org/jclouds/http/internal/WireLiveTest.java index 8729253c38..a3ff8037e7 100644 --- a/core/src/test/java/org/jclouds/http/internal/WireLiveTest.java +++ b/core/src/test/java/org/jclouds/http/internal/WireLiveTest.java @@ -27,6 +27,7 @@ import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; +import java.security.NoSuchAlgorithmException; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; @@ -35,6 +36,7 @@ import org.jclouds.encryption.internal.JCEEncryptionService; import org.jclouds.logging.Logger; import org.testng.annotations.Test; +import com.google.common.base.Throwables; import com.google.common.io.ByteStreams; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -49,7 +51,16 @@ public class WireLiveTest { private static final String sysHttpStreamUrl = System.getProperty("jclouds.wire.httpstream.url"); private static final String sysHttpStreamMd5 = System.getProperty("jclouds.wire.httpstream.md5"); - private static final EncryptionService encryptionService = new JCEEncryptionService(); + private static EncryptionService encryptionService; + + static { + try { + encryptionService = new JCEEncryptionService(); + } catch (NoSuchAlgorithmException e) { + Throwables.propagate(e); + encryptionService = null; + } + } private static class ConnectionTester implements Callable { private final InputStream fromServer; @@ -65,8 +76,7 @@ public class WireLiveTest { ByteStreams.copy(in, out); byte[] compare = encryptionService.md5(new ByteArrayInputStream(out.toByteArray())); Thread.sleep(100); - assertEquals(encryptionService.hex(compare), checkNotNull(sysHttpStreamMd5, - sysHttpStreamMd5)); + assertEquals(encryptionService.hex(compare), checkNotNull(sysHttpStreamMd5, sysHttpStreamMd5)); assertEquals(((BufferLogger) wire.getWireLog()).buff.toString().getBytes().length, 3331484); return null; } @@ -145,8 +155,7 @@ public class WireLiveTest { InputStream in = wire.input(connection.getInputStream()); byte[] compare = encryptionService.md5(in); Thread.sleep(100); - assertEquals(encryptionService.hex(compare), checkNotNull(sysHttpStreamMd5, - sysHttpStreamMd5)); + assertEquals(encryptionService.hex(compare), checkNotNull(sysHttpStreamMd5, sysHttpStreamMd5)); assertEquals(((BufferLogger) wire.getWireLog()).buff.toString().getBytes().length, 3331484); } @@ -155,8 +164,7 @@ public class WireLiveTest { URL url = new URL(checkNotNull(sysHttpStreamUrl, "sysHttpStreamUrl")); URLConnection connection = url.openConnection(); Callable callable = new ConnectionTester(connection.getInputStream()); - ListenableFuture result = Futures - .makeListenable(newCachedThreadPool().submit(callable)); + ListenableFuture result = Futures.makeListenable(newCachedThreadPool().submit(callable)); result.get(30, TimeUnit.SECONDS); } @@ -168,8 +176,7 @@ public class WireLiveTest { InputStream in = wire.input(connection.getInputStream()); byte[] compare = encryptionService.md5(in); Thread.sleep(100); - assertEquals(encryptionService.hex(compare), checkNotNull(sysHttpStreamMd5, - sysHttpStreamMd5)); + assertEquals(encryptionService.hex(compare), checkNotNull(sysHttpStreamMd5, sysHttpStreamMd5)); assertEquals(((BufferLogger) wire.getWireLog()).buff.toString().getBytes().length, 3331484); } diff --git a/extensions/bouncycastle/src/main/java/org/jclouds/encryption/bouncycastle/BouncyCastleEncryptionService.java b/extensions/bouncycastle/src/main/java/org/jclouds/encryption/bouncycastle/BouncyCastleEncryptionService.java index c683ff808c..d2e498e048 100644 --- a/extensions/bouncycastle/src/main/java/org/jclouds/encryption/bouncycastle/BouncyCastleEncryptionService.java +++ b/extensions/bouncycastle/src/main/java/org/jclouds/encryption/bouncycastle/BouncyCastleEncryptionService.java @@ -27,6 +27,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.Key; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; import javax.inject.Singleton; @@ -48,6 +50,13 @@ import org.jclouds.io.payloads.ByteArrayPayload; */ @Singleton public class BouncyCastleEncryptionService extends BaseEncryptionService { + public BouncyCastleEncryptionService(KeyFactory rsaKeyFactory) { + super(rsaKeyFactory); + } + + public BouncyCastleEncryptionService() throws NoSuchAlgorithmException { + super(KeyFactory.getInstance("RSA")); + } @Override public byte[] hmacSha256(String toEncode, byte[] key) { diff --git a/extensions/gae/src/test/java/org/jclouds/gae/ConvertToGaeRequestTest.java b/extensions/gae/src/test/java/org/jclouds/gae/ConvertToGaeRequestTest.java index 1b91e70412..12ee51c30d 100644 --- a/extensions/gae/src/test/java/org/jclouds/gae/ConvertToGaeRequestTest.java +++ b/extensions/gae/src/test/java/org/jclouds/gae/ConvertToGaeRequestTest.java @@ -24,11 +24,13 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; +import java.security.NoSuchAlgorithmException; import java.util.Date; import javax.ws.rs.HttpMethod; import javax.ws.rs.core.HttpHeaders; +import org.jclouds.encryption.EncryptionService; import org.jclouds.encryption.internal.JCEEncryptionService; import org.jclouds.http.HttpRequest; import org.jclouds.io.Payloads; @@ -40,6 +42,7 @@ import org.testng.annotations.Test; import com.google.appengine.api.urlfetch.HTTPHeader; import com.google.appengine.api.urlfetch.HTTPRequest; import com.google.appengine.repackaged.com.google.common.base.Charsets; +import com.google.common.base.Throwables; import com.google.common.io.Files; /** @@ -51,10 +54,19 @@ public class ConvertToGaeRequestTest { ConvertToGaeRequest req; URI endPoint; + protected volatile static EncryptionService encryptionService; + static { + try { + encryptionService = new JCEEncryptionService(); + } catch (NoSuchAlgorithmException e) { + Throwables.propagate(e); + } + } + @BeforeTest void setupClient() throws MalformedURLException { endPoint = URI.create("http://localhost:80/foo"); - req = new ConvertToGaeRequest(new JCEEncryptionService()); + req = new ConvertToGaeRequest(encryptionService); } @Test diff --git a/extensions/gae/src/test/java/org/jclouds/gae/ConvertToJcloudsResponseTest.java b/extensions/gae/src/test/java/org/jclouds/gae/ConvertToJcloudsResponseTest.java index e324634bab..b4088b8628 100644 --- a/extensions/gae/src/test/java/org/jclouds/gae/ConvertToJcloudsResponseTest.java +++ b/extensions/gae/src/test/java/org/jclouds/gae/ConvertToJcloudsResponseTest.java @@ -26,11 +26,13 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import javax.ws.rs.core.HttpHeaders; +import org.jclouds.encryption.EncryptionService; import org.jclouds.encryption.internal.JCEEncryptionService; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpUtils; @@ -40,6 +42,7 @@ import org.testng.annotations.Test; import com.google.appengine.api.urlfetch.HTTPHeader; import com.google.appengine.api.urlfetch.HTTPResponse; +import com.google.common.base.Throwables; /** * @@ -50,10 +53,19 @@ public class ConvertToJcloudsResponseTest { ConvertToJcloudsResponse req; URI endPoint; + protected volatile static EncryptionService encryptionService; + static { + try { + encryptionService = new JCEEncryptionService(); + } catch (NoSuchAlgorithmException e) { + Throwables.propagate(e); + } + } + @BeforeTest void setupClient() throws MalformedURLException { endPoint = URI.create("http://localhost:80/foo"); - req = new ConvertToJcloudsResponse(new HttpUtils(new JCEEncryptionService(), 0, 0, 0, 0)); + req = new ConvertToJcloudsResponse(new HttpUtils(encryptionService, 0, 0, 0, 0)); } @Test diff --git a/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesClientLiveTest.java b/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesClientLiveTest.java index cb5aa92880..7219cc9a85 100644 --- a/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesClientLiveTest.java +++ b/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesClientLiveTest.java @@ -27,6 +27,7 @@ import static org.testng.Assert.fail; import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.URI; +import java.security.NoSuchAlgorithmException; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; @@ -51,6 +52,7 @@ import org.jclouds.util.Utils; import org.testng.annotations.Test; import com.google.common.base.Predicate; +import com.google.common.base.Throwables; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; @@ -61,7 +63,15 @@ import com.google.common.collect.Maps; */ @Test(groups = "live", testName = "cloudfiles.CloudFilesClientLiveTest") public class CloudFilesClientLiveTest extends BaseBlobStoreIntegrationTest { - private static final EncryptionService encryptionService = new JCEEncryptionService(); + + protected volatile static EncryptionService encryptionService; + static { + try { + encryptionService = new JCEEncryptionService(); + } catch (NoSuchAlgorithmException e) { + Throwables.propagate(e); + } + } public CloudFilesClient getApi() { return (CloudFilesClient) context.getProviderSpecificContext().getApi(); @@ -321,7 +331,7 @@ public class CloudFilesClientLiveTest extends BaseBlobStoreIntegrationTest { assertEquals(metadata.getContentType(), null); // assertEquals(metadata.getBytes(), new Long(data.length())); // assertEquals(metadata.getContentType(), "text/plain"); - + assertEquals(encryptionService.hex(md5), encryptionService.hex(metadata.getHash())); assertEquals(metadata.getHash(), encryptionService.fromHex(newEtag)); assertEquals(metadata.getMetadata().entrySet().size(), 1);