mirror of https://github.com/apache/jclouds.git
Issue 191: changed encryption service so that it can decode a PEM key. updated chef to work in google appengine
This commit is contained in:
parent
126460fd1d
commit
7c3518f7ff
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 = "<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>adriancole.org.jclouds.aws.s3.amazons3testdelimiter</Name><Prefix>apps/</Prefix><Marker></Marker><MaxKeys>1000</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>apps/0</Key><LastModified>2009-05-07T18:27:08.000Z</LastModified><ETag>"c82e6a0025c31c5de5947fda62ac51ab"</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/1</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>"944fab2c5a9a6bacf07db5e688310d7a"</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/2</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>"a227b8888045c8fd159fb495214000f0"</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/3</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>"c9caa76c3dec53e2a192608ce73eef03"</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/4</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>"1ce5d0dcc6154a647ea90c7bdf82a224"</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/5</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>"79433524d87462ee05708a8ef894ed55"</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/6</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>"dd00a060b28ddca8bc5a21a49e306f67"</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/7</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>"8cd06eca6e819a927b07a285d750b100"</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/8</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>"174495094d0633b92cbe46603eee6bad"</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/9</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>"cd8a19b26fea8a827276df0ad11c580d"</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListBucketResult>";
|
||||
public static final String listBucketWithSlashDelimiterAndCommonPrefixApps = "<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"> <Delimiter>/</Delimiter> <CommonPrefixes><Prefix>apps/</Prefix></CommonPrefixes></ListBucketResult>";
|
||||
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,64 +68,50 @@ 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"),
|
||||
.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),
|
||||
.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"),
|
||||
.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),
|
||||
.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"),
|
||||
.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),
|
||||
.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"),
|
||||
.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),
|
||||
.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"),
|
||||
.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<String>());
|
||||
.fromHex("cd8a19b26fea8a827276df0ad11c580d"), 8, owner, StorageClass.STANDARD)),
|
||||
"apps/", null, null, 1000, null, false, new TreeSet<String>());
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
|
|
@ -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<SQSClient, SQSAsyncClient> context;
|
||||
|
||||
private EncryptionService encryptionService = new JCEEncryptionService();
|
||||
protected volatile static EncryptionService encryptionService;
|
||||
static {
|
||||
try {
|
||||
encryptionService = new JCEEncryptionService();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Queue> queues = Sets.newHashSet();
|
||||
|
||||
@BeforeGroups(groups = { "live" })
|
||||
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
@ -89,8 +91,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
public static InputSupplier<InputStream> getTestDataSupplier() throws IOException {
|
||||
byte[] oneConstitution = ByteStreams.toByteArray(new GZIPInputStream(BaseJettyTest.class
|
||||
.getResourceAsStream("/const.txt.gz")));
|
||||
InputSupplier<ByteArrayInputStream> constitutionSupplier = ByteStreams
|
||||
.newInputStreamSupplier(oneConstitution);
|
||||
InputSupplier<ByteArrayInputStream> constitutionSupplier = ByteStreams.newInputStreamSupplier(oneConstitution);
|
||||
|
||||
InputSupplier<InputStream> temp = ByteStreams.join(constitutionSupplier);
|
||||
|
||||
|
@ -110,8 +111,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
Map<Integer, ListenableFuture<?>> responses = Maps.newHashMap();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
|
||||
responses.put(i, Futures.compose(context.getAsyncBlobStore()
|
||||
.getBlob(containerName, key), new Function<Blob, Void>() {
|
||||
responses.put(i, Futures.compose(context.getAsyncBlobStore().getBlob(containerName, key),
|
||||
new Function<Blob, Void>() {
|
||||
|
||||
@Override
|
||||
public Void apply(Blob from) {
|
||||
|
@ -122,8 +123,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
|
||||
}));
|
||||
}
|
||||
Map<Integer, Exception> exceptions = awaitCompletion(responses, exec, 30000l,
|
||||
Logger.CONSOLE, "get constitution");
|
||||
Map<Integer, Exception> 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\"" }, { "{great<r}" },
|
||||
{ "lesst>en" }, { "p|pe" } };
|
||||
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" },
|
||||
{ "colon:" }, { "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } };
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" }, dataProvider = "delete")
|
||||
|
@ -365,8 +366,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
}
|
||||
|
||||
private void assertContainerEmptyDeleting(String containerName, String key) {
|
||||
Iterable<? extends StorageMetadata> listing = Iterables.filter(context.getBlobStore().list(
|
||||
containerName), new Predicate<StorageMetadata>() {
|
||||
Iterable<? extends StorageMetadata> listing = Iterables.filter(context.getBlobStore().list(containerName),
|
||||
new Predicate<StorageMetadata>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(StorageMetadata input) {
|
||||
|
@ -401,8 +402,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
}
|
||||
|
||||
@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)));
|
||||
}
|
||||
|
||||
}
|
|
@ -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 = "<apples><apple name=\"%s\"></apple> </apples>";
|
||||
protected static final String TEST_STRING = String.format(XML_STRING_FORMAT, "apple");
|
||||
|
||||
protected Map<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String> containerNames = new ArrayBlockingQueue<String>(
|
||||
containerCount);
|
||||
private volatile static BlockingQueue<String> containerNames = new ArrayBlockingQueue<String>(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<BaseTestInitializer> clazz = (Class<BaseTestInitializer>) 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<BaseTestInitializer> clazz = (Class<BaseTestInitializer>) 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,8 +186,8 @@ public class BaseBlobStoreIntegrationTest {
|
|||
protected static void deleteEverything(final BlobStoreContext context) throws Exception {
|
||||
try {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
Iterable<? extends StorageMetadata> testContainers = Iterables.filter(context
|
||||
.getBlobStore().list(), new Predicate<StorageMetadata>() {
|
||||
Iterable<? extends StorageMetadata> testContainers = Iterables.filter(context.getBlobStore().list(),
|
||||
new Predicate<StorageMetadata>() {
|
||||
public boolean apply(StorageMetadata input) {
|
||||
return (input.getType() == StorageType.CONTAINER || input.getType() == StorageType.FOLDER)
|
||||
&& input.getName().startsWith(CONTAINER_PREFIX.toLowerCase());
|
||||
|
@ -200,8 +209,9 @@ 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 {
|
||||
|
@ -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<String, String> entry : Iterables.concat(fiveStrings.entrySet(),
|
||||
fiveStringsUnderPath.entrySet())) {
|
||||
for (Entry<String, String> entry : Iterables.concat(fiveStrings.entrySet(), fiveStringsUnderPath.entrySet())) {
|
||||
Blob sourceObject = context.getBlobStore().newBlob(entry.getKey());
|
||||
sourceObject.getMetadata().setContentType("text/xml");
|
||||
sourceObject.setPayload(entry.getValue());
|
||||
|
@ -280,9 +289,8 @@ public class BaseBlobStoreIntegrationTest {
|
|||
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<StorageMetadata, String>() {
|
||||
"expected only %d values in %s: %s", count, containerName, Sets.newHashSet(Iterables.transform(
|
||||
context.getBlobStore().list(containerName), new Function<StorageMetadata, String>() {
|
||||
|
||||
public String apply(StorageMetadata from) {
|
||||
return from.getName();
|
||||
|
@ -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<StorageMetadata>() {
|
||||
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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,11 +75,11 @@ 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);
|
||||
|
@ -95,8 +93,7 @@ public class BaseContainerIntegrationTest 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(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<? extends StorageMetadata> container = context.getBlobStore().list(containerName,
|
||||
maxResults(1));
|
||||
PageSet<? extends StorageMetadata> 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<? extends StorageMetadata> container = context.getBlobStore().list(containerName,
|
||||
inDirectory(prefix));
|
||||
PageSet<? extends StorageMetadata> 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<? extends StorageMetadata> container = context.getBlobStore().list(containerName,
|
||||
maxResults(5));
|
||||
PageSet<? extends StorageMetadata> 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");
|
||||
|
|
40
chef/pom.xml
40
chef/pom.xml
|
@ -1,31 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
$HeadURL$
|
||||
$Revision$
|
||||
$Date$
|
||||
|
||||
Copyright (C) 2009 Cloud Conscious, LLC <info@cloudconscious.com>
|
||||
$HeadURL$ $Revision$ $Date$ Copyright (C) 2009 Cloud Conscious, LLC
|
||||
<info@cloudconscious.com>
|
||||
|
||||
====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to you under the Apache License, Version
|
||||
2.0 (the "License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
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.
|
||||
http://www.apache.org/licenses/LICENSE-2.0.html 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.
|
||||
====================================================================
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.jclouds</groupId>
|
||||
|
@ -69,11 +64,6 @@
|
|||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15</artifactId>
|
||||
<version>1.44</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-core</artifactId>
|
||||
|
|
|
@ -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;
|
||||
|
@ -103,8 +101,7 @@ public class BaseChefRestClientModule<S, A> extends RestClientModule<S, A> {
|
|||
*/
|
||||
@Provides
|
||||
@TimeStamp
|
||||
Supplier<String> provideTimeStampCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
|
||||
final DateService dateService) {
|
||||
Supplier<String> provideTimeStampCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds, final DateService dateService) {
|
||||
return new ExpirableSupplier<String>(new Supplier<String>() {
|
||||
public String get() {
|
||||
return dateService.iso8601SecondsDateFormat();
|
||||
|
@ -114,11 +111,9 @@ public class BaseChefRestClientModule<S, A> extends RestClientModule<S, A> {
|
|||
|
||||
@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<S, A> extends RestClientModule<S, A> {
|
|||
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);
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
@ -86,50 +81,38 @@ public class SignedHeaderAuthTest {
|
|||
"NMzYZgyooSvU85qkIUmKuCqgG2AIlvYa2Q/2ctrMhoaHhLOCWWoqYNMaEqPc",
|
||||
"3tKHE+CfvP+WuPdWk4jv4wpIkAz6ZLxToxcGhXmZbXpk56YTmqgBW2cbbw4O",
|
||||
"IWPZDHSiPcw//AYNgW1CCDptt+UFuaFYbtqZegcBd2n/jzcWODA7zL4KWEUy",
|
||||
"9q4rlh/+1tBReg60QdsmDRsw/cdO1GZrKtuCwbuD4+nbRdVBKv72rqHX9cu0",
|
||||
"utju9jzczCyB+sSAQWrxSsXB/b8vV2qs0l4VD2ML+w==" };
|
||||
"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<String, String> EXPECTED_SIGN_RESULT = ImmutableMultimap
|
||||
.<String, String> 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<String, String> EXPECTED_SIGN_RESULT = ImmutableMultimap.<String, String> 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<String, String> EXPECTED_SIGN_RESULT_EMPTY = ImmutableMultimap
|
||||
.<String, String> 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();
|
||||
.<String, String> 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<String, String> headersWithoutContentLength = LinkedHashMultimap.create(request
|
||||
.getHeaders());
|
||||
Multimap<String, String> 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<String, String> headersWithoutContentLength = LinkedHashMultimap.create(request
|
||||
.getHeaders());
|
||||
Multimap<String, String> 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,21 +184,15 @@ public class SignedHeaderAuthTest {
|
|||
@BeforeClass
|
||||
protected void createFilter() throws IOException {
|
||||
|
||||
Injector injector = new RestContextFactory().createContextBuilder("chef", USER_ID,
|
||||
PRIVATE_KEY, ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule()),
|
||||
new Properties()).buildInjector();
|
||||
Injector injector = new RestContextFactory().createContextBuilder("chef", USER_ID, PRIVATE_KEY,
|
||||
ImmutableSet.<Module> 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());
|
||||
|
||||
PrivateKey privateKey = pair.getPrivate();
|
||||
|
||||
signing_obj = new SignedHeaderAuth(new SignatureWire(), USER_ID, privateKey,
|
||||
new Provider<String>() {
|
||||
signing_obj = new SignedHeaderAuth(new SignatureWire(), USER_ID, privateKey, new Provider<String>() {
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
11
core/pom.xml
11
core/pom.xml
|
@ -45,10 +45,21 @@
|
|||
<id>gson</id>
|
||||
<url>http://google-gson.googlecode.com/svn/mavenrepo</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>oauth</id>
|
||||
<name>OAuth Repository</name>
|
||||
<url>http://oauth.googlecode.com/svn/code/maven</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.oauth.core</groupId>
|
||||
<artifactId>oauth</artifactId>
|
||||
<version>20100527</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
<artifactId>aopalliance</artifactId>
|
||||
<version>1.0</version>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -21,15 +21,25 @@ 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
|
||||
|
@ -41,10 +51,14 @@ public abstract class BaseEncryptionService implements EncryptionService {
|
|||
|
||||
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 extends PayloadEnclosing> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
@ -221,8 +229,7 @@ public abstract class BaseJettyTest {
|
|||
public static InputSupplier<InputStream> getTestDataSupplier() throws IOException {
|
||||
byte[] oneConstitution = ByteStreams.toByteArray(new GZIPInputStream(BaseJettyTest.class
|
||||
.getResourceAsStream("/const.txt.gz")));
|
||||
InputSupplier<ByteArrayInputStream> constitutionSupplier = ByteStreams
|
||||
.newInputStreamSupplier(oneConstitution);
|
||||
InputSupplier<ByteArrayInputStream> constitutionSupplier = ByteStreams.newInputStreamSupplier(oneConstitution);
|
||||
|
||||
InputSupplier<InputStream> temp = ByteStreams.join(constitutionSupplier);
|
||||
|
||||
|
@ -232,15 +239,14 @@ public abstract class BaseJettyTest {
|
|||
return temp;
|
||||
}
|
||||
|
||||
public static RestContextBuilder<IntegrationTestClient, IntegrationTestAsyncClient> newBuilder(
|
||||
int testPort, Properties properties, Module... connectionModules) {
|
||||
public static RestContextBuilder<IntegrationTestClient, IntegrationTestAsyncClient> newBuilder(int testPort,
|
||||
Properties properties, Module... connectionModules) {
|
||||
|
||||
ContextSpec<IntegrationTestClient, IntegrationTestAsyncClient> contextSpec = contextSpec(
|
||||
"test", "http://localhost:" + testPort, "1", "identity", null,
|
||||
IntegrationTestClient.class, IntegrationTestAsyncClient.class);
|
||||
ContextSpec<IntegrationTestClient, IntegrationTestAsyncClient> contextSpec = contextSpec("test",
|
||||
"http://localhost:" + testPort, "1", "identity", null, IntegrationTestClient.class,
|
||||
IntegrationTestAsyncClient.class);
|
||||
|
||||
return createContextBuilder(contextSpec, ImmutableSet.<Module> copyOf(connectionModules),
|
||||
properties);
|
||||
return createContextBuilder(contextSpec, ImmutableSet.<Module> 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) {
|
||||
|
|
|
@ -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==");
|
||||
}
|
||||
|
||||
}
|
|
@ -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<Void> {
|
||||
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<Void> callable = new ConnectionTester(connection.getInputStream());
|
||||
ListenableFuture<Void> result = Futures
|
||||
.makeListenable(newCachedThreadPool().submit(callable));
|
||||
ListenableFuture<Void> 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue