Issue 131: extract out bouncycastle

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2408 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-12-13 05:16:26 +00:00
parent 507794042e
commit 1eb4619faa
67 changed files with 2690 additions and 526 deletions

View File

@ -35,6 +35,7 @@ import org.jclouds.http.RequiresHttp;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientFactory;
import org.jclouds.util.EncryptionService;
import ${package}.${clientName};
import ${package}.${clientName}Client;
@ -63,9 +64,10 @@ public class ${clientName}RestClientModule extends AbstractModule {
@Singleton
public BasicAuthentication provideBasicAuthentication(
@Named(${clientName}Constants.PROPERTY_${ucaseClientName}_USER) String user,
@Named(${clientName}Constants.PROPERTY_${ucaseClientName}_PASSWORD) String password)
@Named(${clientName}Constants.PROPERTY_${ucaseClientName}_PASSWORD) String password,
EncryptionService encryptionService)
throws UnsupportedEncodingException {
return new BasicAuthentication(user, password);
return new BasicAuthentication(user, password, encryptionService);
}
@Provides

View File

@ -102,9 +102,9 @@ public class ${clientName}AsyncClientTest extends RestClientTest<${clientName}As
@SuppressWarnings("unused")
@Provides
@Singleton
public BasicAuthentication provideBasicAuthentication()
public BasicAuthentication provideBasicAuthentication(EncryptionService encryptionService)
throws UnsupportedEncodingException {
return new BasicAuthentication("foo", "bar");
return new BasicAuthentication("foo", "bar", encryptionService);
}
};

View File

@ -30,15 +30,18 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.atmosonline.saas.domain.AtmosObject;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils;
import org.jclouds.rest.Binder;
import org.jclouds.util.EncryptionService;
public class BindAtmosObjectToEntityAndMetadataToHeaders implements Binder {
private final BindUserMetadataToHeaders metaBinder;
private final EncryptionService encryptionService;
@Inject
protected BindAtmosObjectToEntityAndMetadataToHeaders(BindUserMetadataToHeaders metaBinder) {
protected BindAtmosObjectToEntityAndMetadataToHeaders(BindUserMetadataToHeaders metaBinder,
EncryptionService encryptionService) {
this.metaBinder = metaBinder;
this.encryptionService = encryptionService;
}
public void bindToRequest(HttpRequest request, Object entity) {
@ -55,7 +58,7 @@ public class BindAtmosObjectToEntityAndMetadataToHeaders implements Binder {
if (object.getContentMetadata().getContentMD5() != null) {
request.getHeaders().put("Content-MD5",
HttpUtils.toBase64String(object.getContentMetadata().getContentMD5()));
encryptionService.toBase64String(object.getContentMetadata().getContentMD5()));
}
metaBinder.bindToRequest(request, object.getUserMetadata());
}

View File

@ -52,15 +52,16 @@ import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.blobstore.strategy.ClearListStrategy;
import org.jclouds.concurrent.FutureFunctionCallable;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.options.GetOptions;
import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.Utils;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
public class AtmosAsyncBlobStore extends BaseAtmosBlobStore implements AsyncBlobStore {
private final EncryptionService encryptionService;
@Inject
public AtmosAsyncBlobStore(AtmosStorageAsyncClient async, AtmosStorageClient sync,
@ -69,10 +70,12 @@ public class AtmosAsyncBlobStore extends BaseAtmosBlobStore implements AsyncBlob
ObjectToBlob object2Blob, BlobToObject blob2Object,
BlobStoreListOptionsToListOptions container2ContainerListOptions,
BlobToHttpGetOptions blob2ObjectGetOptions,
DirectoryEntryListToResourceMetadataList container2ResourceList, ExecutorService service) {
DirectoryEntryListToResourceMetadataList container2ResourceList,
ExecutorService service, EncryptionService encryptionService) {
super(async, sync, blobFactory, logFactory, clearContainerStrategy, object2BlobMd,
object2Blob, blob2Object, container2ContainerListOptions, blob2ObjectGetOptions,
container2ResourceList, service);
this.encryptionService = encryptionService;
}
/**
@ -194,7 +197,7 @@ public class AtmosAsyncBlobStore extends BaseAtmosBlobStore implements AsyncBlob
}
if (blob.getMetadata().getContentMD5() != null)
blob.getMetadata().getUserMetadata().put("content-md5",
HttpUtils.toHexString(blob.getMetadata().getContentMD5()));
encryptionService.toHexString(blob.getMetadata().getContentMD5()));
sync.createFile(container, blob2Object.apply(blob));
return path;
} catch (InterruptedException e) {

View File

@ -47,14 +47,15 @@ import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.domain.Blob.Factory;
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.blobstore.strategy.ClearListStrategy;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.options.GetOptions;
import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.Utils;
import com.google.common.base.Supplier;
public class AtmosBlobStore extends BaseAtmosBlobStore implements BlobStore {
private final EncryptionService encryptionService;
@Inject
public AtmosBlobStore(AtmosStorageAsyncClient async, AtmosStorageClient sync,
@ -63,10 +64,11 @@ public class AtmosBlobStore extends BaseAtmosBlobStore implements BlobStore {
ObjectToBlob object2Blob, BlobToObject blob2Object,
BlobStoreListOptionsToListOptions container2ContainerListOptions,
BlobToHttpGetOptions blob2ObjectGetOptions,
DirectoryEntryListToResourceMetadataList container2ResourceList, ExecutorService service) {
DirectoryEntryListToResourceMetadataList container2ResourceList, ExecutorService service,EncryptionService encryptionService) {
super(async, sync, blobFactory, logFactory, clearContainerStrategy, object2BlobMd,
object2Blob, blob2Object, container2ContainerListOptions, blob2ObjectGetOptions,
container2ResourceList, service);
this.encryptionService = encryptionService;
}
/**
@ -149,7 +151,7 @@ public class AtmosBlobStore extends BaseAtmosBlobStore implements BlobStore {
deleteAndEnsurePathGone(path);
if (blob.getMetadata().getContentMD5() != null)
blob.getMetadata().getUserMetadata().put("content-md5",
HttpUtils.toHexString(blob.getMetadata().getContentMD5()));
encryptionService.toHexString(blob.getMetadata().getContentMD5()));
sync.createFile(container, blob2Object.apply(blob));
return path;
}

View File

@ -35,7 +35,7 @@ import org.jclouds.atmosonline.saas.functions.AtmosObjectName;
import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.ResourceType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.http.HttpUtils;
import org.jclouds.util.EncryptionService;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
@ -50,10 +50,12 @@ public class ObjectToBlobMetadata implements Function<AtmosObject, MutableBlobMe
private static final Set<String> systemMetadata = ImmutableSet.of("atime", "mtime", "ctime",
"itime", "type", "uid", "gid", "objectid", "objname", "size", "nlink", "policyname",
"content-md5");
private final EncryptionService encryptionService;
@Inject
protected ObjectToBlobMetadata(AtmosObjectName objectName) {
protected ObjectToBlobMetadata(AtmosObjectName objectName, EncryptionService encryptionService) {
this.objectName = objectName;
this.encryptionService = encryptionService;
}
public MutableBlobMetadata apply(AtmosObject from) {
@ -62,7 +64,7 @@ public class ObjectToBlobMetadata implements Function<AtmosObject, MutableBlobMe
to.setLastModified(from.getSystemMetadata().getLastUserDataModification());
String md5hex = from.getUserMetadata().getMetadata().get("content-md5");
if (md5hex != null)
to.setContentMD5(HttpUtils.fromHexString(md5hex));
to.setContentMD5(encryptionService.fromHexString(md5hex));
if (from.getContentMetadata().getContentType() != null)
to.setContentType(from.getContentMetadata().getContentType());
to.setName(objectName.apply(from));

View File

@ -45,6 +45,7 @@ import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.internal.SignatureWire;
import org.jclouds.logging.Logger;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.TimeStamp;
import com.google.common.annotations.VisibleForTesting;
@ -63,19 +64,22 @@ public class SignRequest implements HttpRequestFilter {
private final String uid;
private final byte[] key;
private final Provider<String> timeStampProvider;
private final EncryptionService encryptionService;
@Resource
@Named(HttpConstants.SIGNATURE_LOGGER)
Logger signatureLog = Logger.NULL;
@Inject
public SignRequest(SignatureWire signatureWire,
@Named(AtmosStorageConstants.PROPERTY_EMCSAAS_UID) String uid,
@Named(AtmosStorageConstants.PROPERTY_EMCSAAS_KEY) String encodedKey,
@TimeStamp Provider<String> timeStampProvider) {
@TimeStamp Provider<String> timeStampProvider, EncryptionService encryptionService) {
this.signatureWire = signatureWire;
this.uid = uid;
this.key = HttpUtils.fromBase64String(encodedKey);
this.key = encryptionService.fromBase64String(encodedKey);
this.timeStampProvider = timeStampProvider;
this.encryptionService = encryptionService;
}
public void filter(HttpRequest request) throws HttpException {
@ -110,7 +114,7 @@ public class SignRequest implements HttpRequestFilter {
public String signString(String toSign) {
String signature;
try {
signature = HttpUtils.hmacSha1Base64(toSign, key);
signature = encryptionService.hmacSha1Base64(toSign, key);
} catch (Exception e) {
throw new HttpException("error signing request", e);
}
@ -139,12 +143,14 @@ public class SignRequest implements HttpRequestFilter {
if (header.startsWith("x-emc-")) {
// Convert all header names to lowercase.
toSign.append(header.toLowerCase()).append(":");
// For headers with values that span multiple lines, convert them into one line by replacing any
// For headers with values that span multiple lines, convert them into one line by
// replacing any
// newline characters and extra embedded white spaces in the value.
for (String value : request.getHeaders().get(header))
toSign.append(value.replaceAll("\r?\n", "").replaceAll(" ", " ")).append(" ");
toSign.deleteCharAt(toSign.lastIndexOf(" "));
// Concatenate all headers together, using newlines (\n) separating each header from the next one.
// Concatenate all headers together, using newlines (\n) separating each header from the
// next one.
toSign.append("\n");
}
}
@ -155,7 +161,7 @@ public class SignRequest implements HttpRequestFilter {
@VisibleForTesting
void appendHttpHeaders(HttpRequest request, StringBuilder toSign) {
// Only the value is used, not the header
// Only the value is used, not the header
// name. If a request does not include the header, this is an empty string.
for (String header : new String[] { HttpHeaders.CONTENT_TYPE, "Range" })
toSign.append(valueOrEmpty(request.getHeaders().get(header)).toLowerCase()).append("\n");

View File

@ -46,7 +46,6 @@ import org.jclouds.blobstore.binders.BindBlobToMultipartFormTest;
import org.jclouds.blobstore.config.BlobStoreObjectModule;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x;
import org.jclouds.http.functions.ReturnVoidIf2xx;
import org.jclouds.http.options.GetOptions;
@ -57,6 +56,7 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330;
import org.jclouds.util.TimeStamp;
import org.jclouds.util.internal.Base64;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@ -303,7 +303,7 @@ public class AtmosStorageClientTest extends RestClientTest<AtmosStorageAsyncClie
bindConstant().annotatedWith(Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_UID))
.to("uid");
bindConstant().annotatedWith(Jsr330.named(AtmosStorageConstants.PROPERTY_EMCSAAS_KEY))
.to(HttpUtils.toBase64String("key".getBytes()));
.to(Base64.encodeBytes("key".getBytes()));
bind(Logger.LoggerFactory.class).toInstance(new LoggerFactory() {
public Logger getLogger(String category) {
return Logger.NULL;

View File

@ -57,6 +57,7 @@ import org.jclouds.http.internal.SignatureWire;
import org.jclouds.logging.Logger;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.TimeStamp;
import com.google.common.annotations.VisibleForTesting;
@ -80,19 +81,21 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
private final String accessKey;
private final String secretKey;
private final Provider<String> dateService;
private final EncryptionService encryptionService;
@Resource
@Named(HttpConstants.SIGNATURE_LOGGER)
private final Logger signatureLog = Logger.NULL;
private Logger signatureLog = Logger.NULL;
@Inject
public FormSigner(SignatureWire signatureWire,
@Named(AWSConstants.PROPERTY_AWS_ACCESSKEYID) String accessKey,
@Named(AWSConstants.PROPERTY_AWS_SECRETACCESSKEY) String secretKey,
@TimeStamp Provider<String> dateService) {
@TimeStamp Provider<String> dateService, EncryptionService encryptionService) {
this.signatureWire = signatureWire;
this.accessKey = accessKey;
this.secretKey = secretKey;
this.dateService = dateService;
this.encryptionService = encryptionService;
}
public void filter(HttpRequest in) throws HttpException {
@ -157,7 +160,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
public String signString(String stringToSign) {
String signature;
try {
signature = HttpUtils.hmacSha256Base64(stringToSign, secretKey.getBytes());
signature = encryptionService.hmacSha256Base64(stringToSign, secretKey.getBytes());
if (signatureWire.enabled())
signatureWire.input(IOUtils.toInputStream(signature));
} catch (Exception e) {

View File

@ -47,6 +47,7 @@ import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.internal.SignatureWire;
import org.jclouds.logging.Logger;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.TimeStamp;
import com.google.common.annotations.VisibleForTesting;
@ -67,6 +68,8 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
private final String accessKey;
private final String secretKey;
private final Provider<String> timeStampProvider;
private final EncryptionService encryptionService;
@Resource
@Named(HttpConstants.SIGNATURE_LOGGER)
Logger signatureLog = Logger.NULL;
@ -75,11 +78,12 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
public RequestAuthorizeSignature(SignatureWire signatureWire,
@Named(S3Constants.PROPERTY_AWS_ACCESSKEYID) String accessKey,
@Named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY) String secretKey,
@TimeStamp Provider<String> timeStampProvider) {
@TimeStamp Provider<String> timeStampProvider, EncryptionService encryptionService) {
this.signatureWire = signatureWire;
this.accessKey = accessKey;
this.secretKey = secretKey;
this.timeStampProvider = timeStampProvider;
this.encryptionService = encryptionService;
}
public void filter(HttpRequest request) throws HttpException {
@ -115,7 +119,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
public String signString(String toSign) {
String signature;
try {
signature = HttpUtils.hmacSha1Base64(toSign, secretKey.getBytes());
signature = encryptionService.hmacSha1Base64(toSign, secretKey.getBytes());
} catch (Exception e) {
throw new HttpException("error signing request", e);
}

View File

@ -32,9 +32,9 @@ import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.EncryptionService;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
@ -50,12 +50,14 @@ public class ParseObjectMetadataFromHeaders implements
Function<HttpResponse, MutableObjectMetadata>, InvocationContext {
private final ParseSystemAndUserMetadataFromHeaders blobMetadataParser;
private final BlobToObjectMetadata blobToObjectMetadata;
private final EncryptionService encryptionService;
@Inject
public ParseObjectMetadataFromHeaders(ParseSystemAndUserMetadataFromHeaders blobMetadataParser,
BlobToObjectMetadata blobToObjectMetadata) {
BlobToObjectMetadata blobToObjectMetadata, EncryptionService encryptionService) {
this.blobMetadataParser = blobMetadataParser;
this.blobToObjectMetadata = blobToObjectMetadata;
this.encryptionService = encryptionService;
}
/**
@ -66,7 +68,7 @@ public class ParseObjectMetadataFromHeaders implements
BlobMetadata base = blobMetadataParser.apply(from);
MutableObjectMetadata to = blobToObjectMetadata.apply(base);
addETagTo(from, to);
to.setContentMD5(HttpUtils.fromHexString(to.getETag().replaceAll("\"", "")));
to.setContentMD5(encryptionService.fromHexString(to.getETag().replaceAll("\"", "")));
to.setCacheControl(from.getFirstHeaderOrNull(HttpHeaders.CACHE_CONTROL));
to.setContentDisposition(from.getFirstHeaderOrNull("Content-Disposition"));
to.setContentEncoding(from.getFirstHeaderOrNull(HttpHeaders.CONTENT_ENCODING));

View File

@ -34,9 +34,9 @@ import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata.StorageClass;
import org.jclouds.aws.s3.domain.internal.BucketListObjectMetadata;
import org.jclouds.aws.s3.domain.internal.TreeSetListBucketResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.DateService;
import org.jclouds.util.EncryptionService;
import org.xml.sax.Attributes;
import com.google.common.collect.Sets;
@ -58,6 +58,8 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResp
private StringBuilder currentText = new StringBuilder();
private final DateService dateParser;
private final EncryptionService encryptionService;
private String bucketName;
private String prefix;
private String marker;
@ -66,8 +68,9 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResp
private boolean isTruncated;
@Inject
public ListBucketHandler(DateService dateParser) {
public ListBucketHandler(DateService dateParser, EncryptionService encryptionService) {
this.dateParser = dateParser;
this.encryptionService = encryptionService;
this.contents = Sets.newTreeSet();
this.commonPrefixes = Sets.newTreeSet();
}
@ -102,7 +105,7 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResp
currentLastModified = dateParser.iso8601DateParse(currentText.toString().trim());
} else if (qName.equals("ETag")) {
currentETag = currentText.toString().trim();
currentMD5 = HttpUtils.fromHexString(currentETag.replaceAll("\"", ""));
currentMD5 = encryptionService.fromHexString(currentETag.replaceAll("\"", ""));
} else if (qName.equals("Size")) {
currentSize = new Long(currentText.toString().trim());
} else if (qName.equals("Owner")) {

View File

@ -42,7 +42,8 @@ import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.internal.JCEEncryptionService;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
@ -53,6 +54,7 @@ import com.google.common.collect.ImmutableMap;
*/
@Test(testName = "s3.ParseObjectMetadataFromHeadersTest")
public class ParseObjectMetadataFromHeadersTest {
private static final EncryptionService encryptionService = new JCEEncryptionService();
@Test
void testNormal() throws Exception {
@ -62,7 +64,7 @@ public class ParseObjectMetadataFromHeadersTest {
http.getHeaders().put("Content-Disposition", "contentDisposition");
http.getHeaders().put(HttpHeaders.CONTENT_ENCODING, "encoding");
ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http,
"\"abc\""), blobToObjectMetadata);
"\"abc\""), blobToObjectMetadata, encryptionService);
MutableObjectMetadata response = parser.apply(http);
assertEquals(response, expects);
}
@ -76,7 +78,7 @@ public class ParseObjectMetadataFromHeadersTest {
http.getHeaders().put(HttpHeaders.CONTENT_ENCODING, "encoding");
http.getHeaders().put(S3Headers.AMZ_MD5, "\"abc\"");
ParseObjectMetadataFromHeaders parser = new ParseObjectMetadataFromHeaders(blobParser(http,
null), blobToObjectMetadata);
null), blobToObjectMetadata, encryptionService);
MutableObjectMetadata response = parser.apply(http);
assertEquals(response, expects);
}
@ -107,7 +109,7 @@ public class ParseObjectMetadataFromHeadersTest {
expects.setCacheControl("cacheControl");
expects.setContentDisposition("contentDisposition");
expects.setContentEncoding("encoding");
expects.setContentMD5(HttpUtils.fromHexString("abc"));
expects.setContentMD5(encryptionService.fromHexString("abc"));
expects.setContentType("type");
expects.setETag("\"abc\"");
expects.setKey("key");

View File

@ -36,10 +36,11 @@ import org.jclouds.aws.s3.domain.ObjectMetadata.StorageClass;
import org.jclouds.aws.s3.domain.internal.BucketListObjectMetadata;
import org.jclouds.aws.s3.domain.internal.TreeSetListBucketResponse;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.DateService;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.internal.JCEEncryptionService;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
@ -50,6 +51,7 @@ 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>&quot;c82e6a0025c31c5de5947fda62ac51ab&quot;</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>&quot;944fab2c5a9a6bacf07db5e688310d7a&quot;</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>&quot;a227b8888045c8fd159fb495214000f0&quot;</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>&quot;c9caa76c3dec53e2a192608ce73eef03&quot;</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>&quot;1ce5d0dcc6154a647ea90c7bdf82a224&quot;</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>&quot;79433524d87462ee05708a8ef894ed55&quot;</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>&quot;dd00a060b28ddca8bc5a21a49e306f67&quot;</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>&quot;8cd06eca6e819a927b07a285d750b100&quot;</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>&quot;174495094d0633b92cbe46603eee6bad&quot;</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>&quot;cd8a19b26fea8a827276df0ad11c580d&quot;</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();
@BeforeTest
@Override
@ -67,52 +69,52 @@ public class ListBucketHandlerTest extends BaseHandlerTest {
"adriancole.org.jclouds.aws.s3.amazons3testdelimiter", ImmutableList.of(
(ObjectMetadata) new BucketListObjectMetadata("apps/0", dateService
.iso8601DateParse("2009-05-07T18:27:08.000Z"),
"\"c82e6a0025c31c5de5947fda62ac51ab\"", HttpUtils
"\"c82e6a0025c31c5de5947fda62ac51ab\"", encryptionService
.fromHexString("c82e6a0025c31c5de5947fda62ac51ab"), 8,
owner, StorageClass.STANDARD),
(ObjectMetadata) new BucketListObjectMetadata("apps/1", dateService
.iso8601DateParse("2009-05-07T18:27:09.000Z"),
"\"944fab2c5a9a6bacf07db5e688310d7a\"", HttpUtils
"\"944fab2c5a9a6bacf07db5e688310d7a\"", encryptionService
.fromHexString("944fab2c5a9a6bacf07db5e688310d7a"), 8,
owner, StorageClass.STANDARD),
(ObjectMetadata) new BucketListObjectMetadata("apps/2", dateService
.iso8601DateParse("2009-05-07T18:27:09.000Z"),
"\"a227b8888045c8fd159fb495214000f0\"", HttpUtils
"\"a227b8888045c8fd159fb495214000f0\"", encryptionService
.fromHexString("a227b8888045c8fd159fb495214000f0"), 8,
owner, StorageClass.STANDARD),
(ObjectMetadata) new BucketListObjectMetadata("apps/3", dateService
.iso8601DateParse("2009-05-07T18:27:09.000Z"),
"\"c9caa76c3dec53e2a192608ce73eef03\"", HttpUtils
"\"c9caa76c3dec53e2a192608ce73eef03\"", encryptionService
.fromHexString("c9caa76c3dec53e2a192608ce73eef03"), 8,
owner, StorageClass.STANDARD),
(ObjectMetadata) new BucketListObjectMetadata("apps/4", dateService
.iso8601DateParse("2009-05-07T18:27:09.000Z"),
"\"1ce5d0dcc6154a647ea90c7bdf82a224\"", HttpUtils
"\"1ce5d0dcc6154a647ea90c7bdf82a224\"", encryptionService
.fromHexString("1ce5d0dcc6154a647ea90c7bdf82a224"), 8,
owner, StorageClass.STANDARD),
(ObjectMetadata) new BucketListObjectMetadata("apps/5", dateService
.iso8601DateParse("2009-05-07T18:27:09.000Z"),
"\"79433524d87462ee05708a8ef894ed55\"", HttpUtils
"\"79433524d87462ee05708a8ef894ed55\"", encryptionService
.fromHexString("79433524d87462ee05708a8ef894ed55"), 8,
owner, StorageClass.STANDARD),
(ObjectMetadata) new BucketListObjectMetadata("apps/6", dateService
.iso8601DateParse("2009-05-07T18:27:10.000Z"),
"\"dd00a060b28ddca8bc5a21a49e306f67\"", HttpUtils
"\"dd00a060b28ddca8bc5a21a49e306f67\"", encryptionService
.fromHexString("dd00a060b28ddca8bc5a21a49e306f67"), 8,
owner, StorageClass.STANDARD),
(ObjectMetadata) new BucketListObjectMetadata("apps/7", dateService
.iso8601DateParse("2009-05-07T18:27:10.000Z"),
"\"8cd06eca6e819a927b07a285d750b100\"", HttpUtils
"\"8cd06eca6e819a927b07a285d750b100\"", encryptionService
.fromHexString("8cd06eca6e819a927b07a285d750b100"), 8,
owner, StorageClass.STANDARD),
(ObjectMetadata) new BucketListObjectMetadata("apps/8", dateService
.iso8601DateParse("2009-05-07T18:27:10.000Z"),
"\"174495094d0633b92cbe46603eee6bad\"", HttpUtils
"\"174495094d0633b92cbe46603eee6bad\"", encryptionService
.fromHexString("174495094d0633b92cbe46603eee6bad"), 8,
owner, StorageClass.STANDARD),
(ObjectMetadata) new BucketListObjectMetadata("apps/9", dateService
.iso8601DateParse("2009-05-07T18:27:10.000Z"),
"\"cd8a19b26fea8a827276df0ad11c580d\"", HttpUtils
"\"cd8a19b26fea8a827276df0ad11c580d\"", encryptionService
.fromHexString("cd8a19b26fea8a827276df0ad11c580d"), 8,
owner, StorageClass.STANDARD)), "apps/", null, 1000, null, false,
new TreeSet<String>());

View File

@ -35,6 +35,7 @@ import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.azure.storage.blob.reference.AzureBlobConstants;
import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix;
import org.jclouds.http.HttpRequest;
import org.jclouds.util.EncryptionService;
public class BindAzureBlobToEntity extends BindBlobToEntityAndUserMetadataToHeadersWithPrefix {
@ -42,8 +43,9 @@ public class BindAzureBlobToEntity extends BindBlobToEntityAndUserMetadataToHead
@Inject
public BindAzureBlobToEntity(AzureBlobToBlob azureBlob2Blob,
@Named(AzureBlobConstants.PROPERTY_AZUREBLOB_METADATA_PREFIX) String prefix) {
super(prefix);
@Named(AzureBlobConstants.PROPERTY_AZUREBLOB_METADATA_PREFIX) String prefix,
EncryptionService encryptionService) {
super(prefix, encryptionService);
this.azureBlob2Blob = azureBlob2Blob;
}

View File

@ -44,6 +44,7 @@ import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.internal.SignatureWire;
import org.jclouds.logging.Logger;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.TimeStamp;
import com.google.common.annotations.VisibleForTesting;
@ -64,6 +65,7 @@ public class SharedKeyAuthentication implements HttpRequestFilter {
private final String account;
private final byte[] key;
private final Provider<String> timeStampProvider;
private final EncryptionService encryptionService;
@Resource
@Named(HttpConstants.SIGNATURE_LOGGER)
Logger signatureLog = Logger.NULL;
@ -72,10 +74,11 @@ public class SharedKeyAuthentication implements HttpRequestFilter {
public SharedKeyAuthentication(SignatureWire signatureWire,
@Named(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT) String account,
@Named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY) String encodedKey,
@TimeStamp Provider<String> timeStampProvider) {
@TimeStamp Provider<String> timeStampProvider, EncryptionService encryptionService) {
this.encryptionService = encryptionService;
this.signatureWire = signatureWire;
this.account = account;
this.key = HttpUtils.fromBase64String(encodedKey);
this.key = encryptionService.fromBase64String(encodedKey);
this.timeStampProvider = timeStampProvider;
}
@ -111,7 +114,7 @@ public class SharedKeyAuthentication implements HttpRequestFilter {
public String signString(String toSign) {
String signature;
try {
signature = HttpUtils.hmacSha256Base64(toSign, key);
signature = encryptionService.hmacSha256Base64(toSign, key);
} catch (Exception e) {
throw new HttpException("error signing request", e);
}

View File

@ -44,10 +44,11 @@ import org.jclouds.azure.storage.blob.options.CreateContainerOptions;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.options.GetOptions;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.Utils;
import org.jclouds.util.internal.JCEEncryptionService;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
@ -64,6 +65,7 @@ public class AzureBlobClientLiveTest {
protected AzureBlobClient connection;
private String containerPrefix = System.getProperty("user.name") + "-azureblob";
private EncryptionService encryptionService = new JCEEncryptionService();
@BeforeGroups(groups = { "live" })
public void setupClient() {
@ -234,8 +236,8 @@ public class AzureBlobClientLiveTest {
object.getProperties().getMetadata().put("Metadata", "metadata-value");
byte[] md5 = object.getProperties().getContentMD5();
String newEtag = connection.putBlob(privateContainer, object);
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(object.getProperties()
.getContentMD5()));
assertEquals(encryptionService.toHexString(md5), encryptionService.toHexString(object
.getProperties().getContentMD5()));
// Test HEAD of missing object
try {
@ -257,8 +259,8 @@ public class AzureBlobClientLiveTest {
// assertEquals(metadata.getSize(), data.length());
assertEquals(metadata.getContentType(), "text/plain");
// Azure doesn't return the Content-MD5 on head request...
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(object.getProperties()
.getContentMD5()));
assertEquals(encryptionService.toHexString(md5), encryptionService.toHexString(object
.getProperties().getContentMD5()));
assertEquals(metadata.getETag(), newEtag);
assertEquals(metadata.getMetadata().entrySet().size(), 1);
assertEquals(metadata.getMetadata().get("metadata"), "metadata-value");
@ -283,8 +285,8 @@ public class AzureBlobClientLiveTest {
// TODO assertEquals(getBlob.getName(), object.getProperties().getName());
assertEquals(getBlob.getContentLength(), new Long(data.length()));
assertEquals(getBlob.getProperties().getContentType(), "text/plain");
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(getBlob.getProperties()
.getContentMD5()));
assertEquals(encryptionService.toHexString(md5), encryptionService.toHexString(getBlob
.getProperties().getContentMD5()));
assertEquals(newEtag, getBlob.getProperties().getETag());
// wait until we can update metadata
// assertEquals(getBlob.getProperties().getMetadata().entries().size(), 2);
@ -314,8 +316,8 @@ public class AzureBlobClientLiveTest {
object.setData(bais);
object.setContentLength(new Long(data.getBytes().length));
newEtag = connection.putBlob(privateContainer, object);
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(getBlob.getProperties()
.getContentMD5()));
assertEquals(encryptionService.toHexString(md5), encryptionService.toHexString(getBlob
.getProperties().getContentMD5()));
// Test GET with options
// Non-matching ETag

View File

@ -49,7 +49,6 @@ import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReturnTrueIf2xx;
@ -61,6 +60,7 @@ import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330;
import org.jclouds.util.internal.Base64;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@ -356,7 +356,7 @@ public class AzureBlobClientTest {
"myaccount");
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY)).to(
HttpUtils.toBase64String("key".getBytes()));
Base64.encodeBytes("key".getBytes()));
bindConstant().annotatedWith(
Jsr330.named(BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX)).to(
"x-ms-meta-");

View File

@ -31,12 +31,12 @@ import org.jclouds.azure.storage.handlers.ParseAzureStorageErrorFromXmlContent;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.http.handlers.DelegatingErrorHandler;
import org.jclouds.http.handlers.DelegatingRetryHandler;
import org.jclouds.http.handlers.RedirectionRetryHandler;
import org.jclouds.util.Jsr330;
import org.jclouds.util.internal.Base64;
import org.testng.annotations.Test;
import com.google.inject.AbstractModule;
@ -58,7 +58,7 @@ public class RestAzureBlobClientModuleTest {
Jsr330.named(AzureBlobConstants.PROPERTY_AZURESTORAGE_ACCOUNT)).to("user");
bindConstant()
.annotatedWith(Jsr330.named(AzureBlobConstants.PROPERTY_AZURESTORAGE_KEY)).to(
HttpUtils.toBase64String("secret".getBytes()));
Base64.encodeBytes("secret".getBytes()));
bindConstant().annotatedWith(
Jsr330.named(AzureBlobConstants.PROPERTY_AZUREBLOB_ENDPOINT)).to(
"http://localhost");

View File

@ -36,9 +36,9 @@ import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.util.Jsr330;
import org.jclouds.util.internal.Base64;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@ -50,7 +50,7 @@ import com.google.inject.Injector;
@Test(groups = "unit", testName = "azurestorage.SharedKeyAuthenticationTest")
public class SharedKeyAuthenticationTest {
private static final String KEY = HttpUtils.toBase64String("bar".getBytes());
private static final String KEY = Base64.encodeBytes("bar".getBytes());
private static final String ACCOUNT = "foo";
private Injector injector;
private SharedKeyAuthentication filter;

View File

@ -40,7 +40,6 @@ import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReturnTrueIf2xx;
@ -50,6 +49,7 @@ import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330;
import org.jclouds.util.internal.Base64;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@ -179,7 +179,7 @@ public class AzureQueueClientTest {
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT)).to("user");
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY)).to(
HttpUtils.toBase64String("key".getBytes()));
Base64.encodeBytes("key".getBytes()));
bind(Logger.LoggerFactory.class).toInstance(new LoggerFactory() {
public Logger getLogger(String category) {
return Logger.NULL;

View File

@ -25,14 +25,25 @@ package org.jclouds.blobstore.binders;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils;
import org.jclouds.rest.Binder;
import org.jclouds.util.EncryptionService;
/**
*
* @author Adrian Cole
*/
public class BindBlobToEntity implements Binder {
private final EncryptionService encryptionService;
@Inject
public BindBlobToEntity(EncryptionService encryptionService) {
this.encryptionService = encryptionService;
}
public void bindToRequest(HttpRequest request, Object entity) {
Blob object = (Blob) entity;
@ -48,7 +59,7 @@ public class BindBlobToEntity implements Binder {
if (object.getMetadata().getContentMD5() != null) {
request.getHeaders().put("Content-MD5",
HttpUtils.toBase64String(object.getMetadata().getContentMD5()));
encryptionService.toBase64String(object.getMetadata().getContentMD5()));
}
}
}

View File

@ -30,13 +30,20 @@ import javax.inject.Named;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest;
import org.jclouds.util.EncryptionService;
/**
*
* @author Adrian Cole
*/
public class BindBlobToEntityAndUserMetadataToHeadersWithPrefix extends BindBlobToEntity {
private final String metadataPrefix;
@Inject
public BindBlobToEntityAndUserMetadataToHeadersWithPrefix(
@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix,
EncryptionService encryptionService) {
super(encryptionService);
this.metadataPrefix = metadataPrefix;
}

View File

@ -23,7 +23,7 @@
*/
package org.jclouds.blobstore.functions;
import org.jclouds.blobstore.functions.impl.BouncyCastleGenerateMD5;
import org.jclouds.blobstore.functions.impl.JCEGenerateMD5;
import com.google.common.base.Function;
import com.google.inject.ImplementedBy;
@ -32,7 +32,7 @@ import com.google.inject.ImplementedBy;
*
* @author Adrian Cole
*/
@ImplementedBy(BouncyCastleGenerateMD5.class)
@ImplementedBy(JCEGenerateMD5.class)
public interface GenerateMD5 extends Function<Object, byte[]> {
}

View File

@ -26,7 +26,7 @@ package org.jclouds.blobstore.functions;
import java.io.InputStream;
import org.jclouds.blobstore.domain.MD5InputStreamResult;
import org.jclouds.blobstore.functions.impl.BouncyCastleGenerateMD5Result;
import org.jclouds.blobstore.functions.impl.JCEGenerateMD5Result;
import com.google.common.base.Function;
import com.google.inject.ImplementedBy;
@ -35,7 +35,7 @@ import com.google.inject.ImplementedBy;
*
* @author Adrian Cole
*/
@ImplementedBy(BouncyCastleGenerateMD5Result.class)
@ImplementedBy(JCEGenerateMD5Result.class)
public interface GenerateMD5Result extends Function<InputStream, MD5InputStreamResult> {
}

View File

@ -35,10 +35,10 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.DateService;
import org.jclouds.util.EncryptionService;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
@ -51,14 +51,17 @@ public class ParseSystemAndUserMetadataFromHeaders implements
private final String metadataPrefix;
private final DateService dateParser;
private final Provider<MutableBlobMetadata> metadataFactory;
private final EncryptionService encryptionService;
private GeneratedHttpRequest<?> request;
@Inject
public ParseSystemAndUserMetadataFromHeaders(Provider<MutableBlobMetadata> metadataFactory,
DateService dateParser, @Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) {
DateService dateParser, @Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix,
EncryptionService encryptionService) {
this.metadataFactory = metadataFactory;
this.dateParser = dateParser;
this.metadataPrefix = metadataPrefix;
this.encryptionService = encryptionService;
}
public MutableBlobMetadata apply(HttpResponse from) {
@ -115,7 +118,7 @@ public class ParseSystemAndUserMetadataFromHeaders implements
protected void addContentMD5To(HttpResponse from, MutableBlobMetadata metadata) {
String contentMD5 = from.getFirstHeaderOrNull("Content-MD5");
if (contentMD5 != null) {
metadata.setContentMD5(HttpUtils.fromBase64String(contentMD5));
metadata.setContentMD5(encryptionService.fromBase64String(contentMD5));
}
}

View File

@ -26,17 +26,19 @@ package org.jclouds.blobstore.functions.impl;
import javax.inject.Singleton;
import org.jclouds.blobstore.functions.GenerateMD5;
import org.jclouds.http.HttpUtils;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.internal.JCEEncryptionService;
/**
*
* @author Adrian Cole
*/
@Singleton
public class BouncyCastleGenerateMD5 implements GenerateMD5 {
public class JCEGenerateMD5 implements GenerateMD5 {
private static final EncryptionService encryptionService = new JCEEncryptionService();
public byte[] apply(Object from) {
return HttpUtils.md5(from);
return encryptionService.md5(from);
}
}

View File

@ -23,47 +23,26 @@
*/
package org.jclouds.blobstore.functions.impl;
import java.io.IOException;
import java.io.InputStream;
import javax.inject.Singleton;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.jclouds.blobstore.domain.MD5InputStreamResult;
import org.jclouds.blobstore.functions.GenerateMD5Result;
import org.jclouds.blobstore.internal.BlobRuntimeException;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.internal.JCEEncryptionService;
/**
*
* @author Adrian Cole
*/
@Singleton
public class BouncyCastleGenerateMD5Result implements GenerateMD5Result {
public class JCEGenerateMD5Result implements GenerateMD5Result {
private static final EncryptionService encryptionService = new JCEEncryptionService();
public MD5InputStreamResult apply(InputStream toEncode) {
MD5Digest eTag = new MD5Digest();
byte[] resBuf = new byte[eTag.getDigestSize()];
byte[] buffer = new byte[1024];
ByteArrayOutputStream out = new ByteArrayOutputStream();
long length = 0;
int numRead = -1;
try {
do {
numRead = toEncode.read(buffer);
if (numRead > 0) {
length += numRead;
eTag.update(buffer, 0, numRead);
out.write(buffer, 0, numRead);
}
} while (numRead != -1);
} catch (IOException e) {
throw new BlobRuntimeException("couldn't get MD5 for: " + toEncode, e);
} finally {
IOUtils.closeQuietly(out);
IOUtils.closeQuietly(toEncode);
}
eTag.doFinal(resBuf, 0);
return new MD5InputStreamResult(out.toByteArray(), resBuf, length);
org.jclouds.util.EncryptionService.MD5InputStreamResult result = encryptionService
.generateMD5Result(toEncode);
return new MD5InputStreamResult(result.data, result.md5, result.length);
}
}

View File

@ -40,6 +40,7 @@ import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.internal.JCEEncryptionService;
import org.jclouds.util.internal.SimpleDateFormatDateService;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
@ -62,7 +63,7 @@ public class ParseBlobMetadataFromHeadersTest {
void setUp() {
parser = new ParseSystemAndUserMetadataFromHeaders(blobMetadataProvider,
new SimpleDateFormatDateService(), "prefix");
new SimpleDateFormatDateService(), "prefix", new JCEEncryptionService());
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();

View File

@ -46,7 +46,7 @@ import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.HttpUtils;
import org.jclouds.util.internal.JCEEncryptionService;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@ -329,7 +329,7 @@ public class BaseBlobIntegrationTest<A, S> extends BaseBlobStoreIntegrationTest<
// 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(HttpUtils.md5(TEST_STRING.getBytes()));
object.getMetadata().setContentMD5(new JCEEncryptionService().md5(TEST_STRING.getBytes()));
String containerName = getContainerName();
try {
addBlobToContainer(containerName, object);
@ -356,7 +356,7 @@ public class BaseBlobIntegrationTest<A, S> 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(), HttpUtils.md5(TEST_STRING.getBytes()));
assertEquals(metadata.getContentMD5(), new JCEEncryptionService().md5(TEST_STRING.getBytes()));
}
}

View File

@ -31,7 +31,7 @@ import java.net.URL;
import java.net.URLConnection;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpUtils;
import org.jclouds.util.internal.JCEEncryptionService;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
@ -64,7 +64,7 @@ public class BaseBlobLiveTest<A, S> extends BaseBlobStoreIntegrationTest<A, S> {
String key = "hello";
URL url = new URL(httpStreamUrl);
byte[] md5 = HttpUtils.fromHexString(httpStreamETag);
byte[] md5 = new JCEEncryptionService().fromHexString(httpStreamETag);
URLConnection connection = url.openConnection();
int length = connection.getContentLength();

View File

@ -82,9 +82,9 @@ import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.options.HttpRequestOptions;
import org.jclouds.util.DateService;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.Utils;
import com.google.common.base.Function;
@ -105,6 +105,7 @@ import com.google.inject.internal.Nullable;
public class StubAsyncBlobStore implements AsyncBlobStore {
protected final DateService dateService;
protected final EncryptionService encryptionService;
private final ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs;
protected final Blob.Factory blobProvider;
protected final HttpGetOptionsListToGetOptions httpGetOptionsConverter;
@ -117,11 +118,12 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
@Inject
protected StubAsyncBlobStore(
ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
DateService dateService, Blob.Factory blobProvider,
GetDirectoryStrategy getDirectoryStrategy, MkdirStrategy mkdirStrategy,
IsDirectoryStrategy isDirectoryStrategy,
DateService dateService, EncryptionService encryptionService,
Blob.Factory blobProvider, GetDirectoryStrategy getDirectoryStrategy,
MkdirStrategy mkdirStrategy, IsDirectoryStrategy isDirectoryStrategy,
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ExecutorService service) {
this.dateService = checkNotNull(dateService, "dateService");
this.encryptionService = checkNotNull(encryptionService, "encryptionService");
this.containerToBlobs = checkNotNull(containerToBlobs, "containerToBlobs");
this.blobProvider = checkNotNull(blobProvider, "blobProvider");
this.getDirectoryStrategy = checkNotNull(getDirectoryStrategy, "getDirectoryStrategy");
@ -514,8 +516,8 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
object.getMetadata().setSize(data.length);
MutableBlobMetadata newMd = copy(object.getMetadata());
newMd.setLastModified(new Date());
final byte[] md5 = HttpUtils.md5(data);
final String eTag = HttpUtils.toHexString(md5);
final byte[] md5 = encryptionService.md5(data);
final String eTag = encryptionService.toHexString(md5);
newMd.setETag(eTag);
newMd.setContentMD5(md5);
newMd.setContentType(object.getMetadata().getContentType());

View File

@ -94,11 +94,6 @@
<version>7.0.0pre3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15</artifactId>
<version>1.44</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>

View File

@ -23,13 +23,10 @@
*/
package org.jclouds.http;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -37,9 +34,6 @@ import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -49,16 +43,7 @@ import java.util.regex.Pattern;
import javax.annotation.Resource;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Base64;
import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
@ -73,6 +58,18 @@ public class HttpUtils {
public static final Pattern URI_PATTERN = Pattern.compile("([a-z0-9]+)://([^:]*):(.*)@(.*)");
public static final Pattern PATTERN_THAT_BREAKS_URI = Pattern.compile("[a-z0-9]+://.*/.*@.*"); // slash
public static Long calculateSize(Object data) {
Long size = null;
if (data instanceof byte[]) {
size = new Long(((byte[]) data).length);
} else if (data instanceof String) {
size = new Long(((String) data).length());
} else if (data instanceof File) {
size = ((File) data).length();
}
return size;
}
@Resource
protected static Logger logger = Logger.NULL;
@ -198,25 +195,6 @@ public class HttpUtils {
public static final Pattern IP_PATTERN = Pattern
.compile("b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)"
+ "{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)b");
static 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' };
public static String toHexString(byte[] raw) {
byte[] hex = new byte[2 * raw.length];
int index = 0;
for (byte b : raw) {
int v = b & 0xFF;
hex[index++] = HEX_CHAR_TABLE[v >>> 4];
hex[index++] = HEX_CHAR_TABLE[v & 0xF];
}
try {
return new String(hex, "ASCII");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public static void logRequest(Logger logger, HttpRequest request, String prefix) {
if (logger.isDebugEnabled()) {
@ -237,165 +215,6 @@ public class HttpUtils {
}
}
public static byte[] fromHexString(String hex) {
if (hex.startsWith("0x"))
hex = hex.substring(2);
byte[] bytes = new byte[hex.length() / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
}
return bytes;
}
public static String hmacSha256Base64(String toEncode, byte[] key)
throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException {
Digest digest = new SHA256Digest();
return hmacBase64(toEncode, key, digest);
}
private static String hmacBase64(String toEncode, byte[] key, Digest digest) {
byte[] resBuf = hmac(toEncode, key, digest);
return toBase64String(resBuf);
}
public static byte[] hmac(String toEncode, byte[] key, Digest digest) {
HMac hmac = new HMac(digest);
byte[] resBuf = new byte[hmac.getMacSize()];
byte[] plainBytes = Utils.encodeString(toEncode);
byte[] keyBytes = key;
hmac.init(new KeyParameter(keyBytes));
hmac.update(plainBytes, 0, plainBytes.length);
hmac.doFinal(resBuf, 0);
return resBuf;
}
public static String hmacSha1Base64(String toEncode, byte[] key)
throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException {
Digest digest = new SHA1Digest();
return hmacBase64(toEncode, key, digest);
}
public static String md5Hex(byte[] toEncode) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException, UnsupportedEncodingException {
byte[] resBuf = md5(toEncode);
return toHexString(resBuf);
}
public static String md5Base64(byte[] toEncode) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException {
byte[] resBuf = md5(toEncode);
return toBase64String(resBuf);
}
public static byte[] md5(byte[] plainBytes) {
MD5Digest eTag = new MD5Digest();
byte[] resBuf = new byte[eTag.getDigestSize()];
eTag.update(plainBytes, 0, plainBytes.length);
eTag.doFinal(resBuf, 0);
return resBuf;
}
public static byte[] md5(File toEncode) {
MD5Digest eTag = new MD5Digest();
byte[] resBuf = new byte[eTag.getDigestSize()];
byte[] buffer = new byte[1024];
int numRead = -1;
InputStream i = null;
try {
i = new FileInputStream(toEncode);
do {
numRead = i.read(buffer);
if (numRead > 0) {
eTag.update(buffer, 0, numRead);
}
} while (numRead != -1);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(i);
}
eTag.doFinal(resBuf, 0);
return resBuf;
}
public static String toBase64String(byte[] resBuf) {
return new String(Base64.encode(resBuf));
}
public static Long calculateSize(Object data) {
Long size = null;
if (data instanceof byte[]) {
size = new Long(((byte[]) data).length);
} else if (data instanceof String) {
size = new Long(((String) data).length());
} else if (data instanceof File) {
size = ((File) data).length();
}
return size;
}
/**
* @throws IOException
*/
public static byte[] md5(Object data) {
checkNotNull(data, "data must be set before calling generateETag()");
byte[] md5 = null;
if (data == null) {
} else if (data instanceof byte[]) {
md5 = md5((byte[]) data);
} else if (data instanceof String) {
md5 = md5(((String) data).getBytes());
} else if (data instanceof File) {
md5 = md5(((File) data));
} else if (data instanceof InputStream) {
md5 = generateMD5Result(((InputStream) data)).md5;
} else {
throw new UnsupportedOperationException("Content not supported " + data.getClass());
}
return md5;
}
public static MD5InputStreamResult generateMD5Result(InputStream toEncode) {
MD5Digest eTag = new MD5Digest();
byte[] resBuf = new byte[eTag.getDigestSize()];
byte[] buffer = new byte[1024];
ByteArrayOutputStream out = new ByteArrayOutputStream();
long length = 0;
int numRead = -1;
try {
do {
numRead = toEncode.read(buffer);
if (numRead > 0) {
length += numRead;
eTag.update(buffer, 0, numRead);
out.write(buffer, 0, numRead);
}
} while (numRead != -1);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(out);
IOUtils.closeQuietly(toEncode);
}
eTag.doFinal(resBuf, 0);
return new MD5InputStreamResult(out.toByteArray(), resBuf, length);
}
public static class MD5InputStreamResult {
public final byte[] data;
public final byte[] md5;
public final long length;
MD5InputStreamResult(byte[] data, byte[] eTag, long length) {
this.data = checkNotNull(data, "data");
this.md5 = checkNotNull(eTag, "eTag");
checkArgument(length >= 0, "length cannot me negative");
this.length = length;
}
}
public static void copy(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[1024];
long length = 0;
@ -425,8 +244,4 @@ public class HttpUtils {
return buffer.toString();
}
public static byte[] fromBase64String(String encoded) {
return Base64.decode(encoded);
}
}

View File

@ -35,7 +35,7 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils;
import org.jclouds.util.EncryptionService;
/**
* Uses Basic Authentication to sign the request.
@ -47,12 +47,14 @@ import org.jclouds.http.HttpUtils;
@Singleton
public class BasicAuthentication implements HttpRequestFilter {
private List<String> credentialList;
private final List<String> credentialList;
public BasicAuthentication(String user, String password) throws UnsupportedEncodingException {
public BasicAuthentication(String user, String password, EncryptionService encryptionService)
throws UnsupportedEncodingException {
this.credentialList = Collections.singletonList("Basic "
+ HttpUtils.toBase64String(String.format("%s:%s", checkNotNull(user, "user"),
checkNotNull(password, "password")).getBytes("UTF-8")));
+ encryptionService.toBase64String(String.format("%s:%s",
checkNotNull(user, "user"), checkNotNull(password, "password")).getBytes(
"UTF-8")));
}
public void filter(HttpRequest request) throws HttpException {

View File

@ -27,17 +27,18 @@ import javax.annotation.Resource;
import org.apache.commons.io.IOUtils;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.logging.Logger;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.internal.Base64;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]>, InvocationContext {
public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]>,
InvocationContext {
public static class NoContentMD5Exception extends RuntimeException {
@ -69,7 +70,7 @@ public class ParseContentMD5FromHeaders implements Function<HttpResponse, byte[]
IOUtils.closeQuietly(from.getContent());
String contentMD5 = from.getFirstHeaderOrNull("Content-MD5");
if (contentMD5 != null) {
return HttpUtils.fromBase64String(contentMD5);
return Base64.decode(contentMD5);
}
throw new NoContentMD5Exception(request, from);
}

View File

@ -0,0 +1,89 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.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
* 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.util;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import org.jclouds.util.internal.JCEEncryptionService;
import com.google.inject.ImplementedBy;
/**
*
* @author Adrian Cole
*/
@ImplementedBy(JCEEncryptionService.class)
public interface EncryptionService {
String toHexString(byte[] raw);
byte[] fromHexString(String hex);
String hmacSha256Base64(String toEncode, byte[] key) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException;
String hmacSha1Base64(String toEncode, byte[] key) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException;
String md5Hex(byte[] toEncode) throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException, UnsupportedEncodingException;
String md5Base64(byte[] toEncode) throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException;
byte[] md5(byte[] plainBytes);
byte[] md5(File toEncode);
String toBase64String(byte[] resBuf);
byte[] md5(Object data);
MD5InputStreamResult generateMD5Result(InputStream toEncode);
public static class MD5InputStreamResult {
public final byte[] data;
public final byte[] md5;
public final long length;
public MD5InputStreamResult(byte[] data, byte[] eTag, long length) {
this.data = checkNotNull(data, "data");
this.md5 = checkNotNull(eTag, "eTag");
checkArgument(length >= 0, "length cannot me negative");
this.length = length;
}
}
byte[] fromBase64String(String encoded);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,85 @@
package org.jclouds.util.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import org.jclouds.util.EncryptionService;
/**
*
* @author Adrian Cole
*/
public abstract class BaseEncryptionService implements EncryptionService {
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' };
public String toHexString(byte[] raw) {
byte[] hex = new byte[2 * raw.length];
int index = 0;
for (byte b : raw) {
int v = b & 0xFF;
hex[index++] = HEX_CHAR_TABLE[v >>> 4];
hex[index++] = HEX_CHAR_TABLE[v & 0xF];
}
try {
return new String(hex, "ASCII");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public byte[] fromHexString(String hex) {
if (hex.startsWith("0x"))
hex = hex.substring(2);
byte[] bytes = new byte[hex.length() / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
}
return bytes;
}
public String md5Hex(byte[] toEncode) throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException, UnsupportedEncodingException {
byte[] resBuf = md5(toEncode);
return toHexString(resBuf);
}
public String md5Base64(byte[] toEncode) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException {
byte[] resBuf = md5(toEncode);
return toBase64String(resBuf);
}
/**
* @throws IOException
*/
public byte[] md5(Object data) {
checkNotNull(data, "data must be set before calling generateETag()");
byte[] md5 = null;
if (data == null) {
} else if (data instanceof byte[]) {
md5 = md5((byte[]) data);
} else if (data instanceof String) {
md5 = md5(((String) data).getBytes());
} else if (data instanceof File) {
md5 = md5(((File) data));
} else if (data instanceof InputStream) {
md5 = generateMD5Result(((InputStream) data)).md5;
} else {
throw new UnsupportedOperationException("Content not supported " + data.getClass());
}
return md5;
}
}

View File

@ -0,0 +1,125 @@
package org.jclouds.util.internal;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
/**
*
* @author Adrian Cole
*/
public class JCEEncryptionService extends BaseEncryptionService {
public String hmacSha256Base64(String toEncode, byte[] key) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException {
return hmacBase64(toEncode, key, "HmacSHA256");
}
private String hmacBase64(String toEncode, byte[] key, String algorithm) {
byte[] resBuf = hmac(toEncode, key, algorithm);
return toBase64String(resBuf);
}
public byte[] hmac(String toEncode, byte[] key, String algorithm) {
SecretKeySpec signingKey = new SecretKeySpec(key, algorithm);
Mac mac = null;
try {
mac = Mac.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Could not find the " + algorithm + " algorithm", e);
}
try {
mac.init(signingKey);
} catch (InvalidKeyException e) {
throw new RuntimeException("Could not initialize the " + algorithm + " algorithm", e);
}
return mac.doFinal(toEncode.getBytes());
}
public String hmacSha1Base64(String toEncode, byte[] key) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException {
return hmacBase64(toEncode, key, "HmacSHA1");
}
public byte[] md5(byte[] plainBytes) {
MessageDigest eTag = getDigest();
eTag.update(plainBytes, 0, plainBytes.length);
return eTag.digest();
}
public byte[] md5(File toEncode) {
MessageDigest eTag = getDigest();
byte[] buffer = new byte[1024];
int numRead = -1;
InputStream i = null;
try {
i = new FileInputStream(toEncode);
do {
numRead = i.read(buffer);
if (numRead > 0) {
eTag.update(buffer, 0, numRead);
}
} while (numRead != -1);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(i);
}
return eTag.digest();
}
public String toBase64String(byte[] resBuf) {
return Base64.encodeBytes(resBuf);
}
public MD5InputStreamResult generateMD5Result(InputStream toEncode) {
MessageDigest eTag = getDigest();
byte[] buffer = new byte[1024];
ByteArrayOutputStream out = new ByteArrayOutputStream();
long length = 0;
int numRead = -1;
try {
do {
numRead = toEncode.read(buffer);
if (numRead > 0) {
length += numRead;
eTag.update(buffer, 0, numRead);
out.write(buffer, 0, numRead);
}
} while (numRead != -1);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(out);
IOUtils.closeQuietly(toEncode);
}
return new MD5InputStreamResult(out.toByteArray(), eTag.digest(), length);
}
private MessageDigest getDigest() {
MessageDigest eTag;
try {
eTag = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Could not find the MD5 algorithm", e);
}
return eTag;
}
public byte[] fromBase64String(String encoded) {
return Base64.decode(encoded);
}
}

View File

@ -0,0 +1,172 @@
/**
*
* 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
* 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.util.internal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.SimpleTimeZone;
import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.ThreadSafe;
import org.jclouds.util.DateService;
/**
*
* uses {@link SimpleDateFormat} internally.
*
* @author Adrian Cole
* @author James Murty
*/
@ThreadSafe
public class SimpleDateFormatDateService implements DateService {
/*
* Use default Java Date/SimpleDateFormat classes for date manipulation, but be *very* careful to
* guard against the lack of thread safety.
*/
@GuardedBy("this")
private static final SimpleDateFormat iso8601SecondsSimpleDateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
@GuardedBy("this")
private static final SimpleDateFormat iso8601SimpleDateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
@GuardedBy("this")
private static final SimpleDateFormat rfc822SimpleDateFormat = new SimpleDateFormat(
"EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
@GuardedBy("this")
private static final SimpleDateFormat cSimpleDateFormat = new SimpleDateFormat(
"EEE MMM dd HH:mm:ss '+0000' yyyy", Locale.US);
static {
iso8601SimpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
iso8601SecondsSimpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
rfc822SimpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
cSimpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
}
public final Date fromSeconds(long seconds) {
return new Date(seconds * 1000);
}
public final String cDateFormat(Date date) {
synchronized (cSimpleDateFormat) {
return cSimpleDateFormat.format(date);
}
}
public final String cDateFormat() {
return cDateFormat(new Date());
}
public final Date cDateParse(String toParse) {
synchronized (cSimpleDateFormat) {
try {
return cSimpleDateFormat.parse(toParse);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
public final String rfc822DateFormat(Date date) {
synchronized (rfc822SimpleDateFormat) {
return rfc822SimpleDateFormat.format(date);
}
}
public final String rfc822DateFormat() {
return rfc822DateFormat(new Date());
}
public final Date rfc822DateParse(String toParse) {
synchronized (rfc822SimpleDateFormat) {
try {
return rfc822SimpleDateFormat.parse(toParse);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
public final String iso8601SecondsDateFormat() {
return iso8601SecondsDateFormat(new Date());
}
public final String iso8601DateFormat(Date date) {
synchronized (iso8601SimpleDateFormat) {
return iso8601SimpleDateFormat.format(date);
}
}
public final String iso8601DateFormat() {
return iso8601DateFormat(new Date());
}
public final Date iso8601DateParse(String toParse) {
toParse = trimNanosToMillis(toParse);
synchronized (iso8601SimpleDateFormat) {
try {
return iso8601SimpleDateFormat.parse(toParse);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
private String trimNanosToMillis(String toParse) {
if (toParse.matches(".*[0-9][0-9][0-9][0-9][0-9][0-9]"))
toParse = toParse.substring(0, toParse.length() - 3) + 'Z';
return toParse;
}
private String trimTZ(String toParse) {
if (toParse.length() == 25 && toParse.matches(".*[0-2][0-9]:00"))
toParse = toParse.substring(0, toParse.length() - 6) + 'Z';
return toParse;
}
public final Date iso8601SecondsDateParse(String toParse) {
toParse = trimTZ(toParse);
synchronized (iso8601SecondsSimpleDateFormat) {
try {
return iso8601SecondsSimpleDateFormat.parse(toParse);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
@Override
public String iso8601SecondsDateFormat(Date date) {
synchronized (iso8601SecondsSimpleDateFormat) {
return iso8601SecondsSimpleDateFormat.format(date);
}
}
}

View File

@ -31,6 +31,7 @@ import java.net.URI;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.http.HttpRequest;
import org.jclouds.util.internal.JCEEncryptionService;
import org.testng.annotations.Test;
/**
@ -45,7 +46,7 @@ public class BasicAuthenticationTest {
public void testAuth() throws UnsupportedEncodingException {
BasicAuthentication filter = new BasicAuthentication(USER, PASSWORD);
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),

View File

@ -39,9 +39,9 @@ import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.internal.HttpWire;
import org.jclouds.logging.Logger;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.internal.JCEEncryptionService;
import org.testng.annotations.Test;
/**
@ -54,6 +54,8 @@ 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 class ConnectionTester implements Callable<Void> {
private final InputStream fromServer;
@ -66,9 +68,9 @@ public class WireLiveTest {
InputStream in = wire.input(fromServer);
ByteArrayOutputStream out = new ByteArrayOutputStream();
IOUtils.copy(in, out);
byte[] compare = HttpUtils.md5(new ByteArrayInputStream(out.toByteArray()));
byte[] compare = encryptionService.md5(new ByteArrayInputStream(out.toByteArray()));
Thread.sleep(100);
assertEquals(HttpUtils.toHexString(compare), checkNotNull(sysHttpStreamMd5,
assertEquals(encryptionService.toHexString(compare), checkNotNull(sysHttpStreamMd5,
sysHttpStreamMd5));
assertEquals(((BufferLogger) wire.getWireLog()).buff.toString().getBytes().length, 3331484);
return null;
@ -148,9 +150,10 @@ public class WireLiveTest {
URLConnection connection = url.openConnection();
HttpWire wire = setUp();
InputStream in = wire.input(connection.getInputStream());
byte[] compare = HttpUtils.md5(in);
byte[] compare = encryptionService.md5(in);
Thread.sleep(100);
assertEquals(HttpUtils.toHexString(compare), checkNotNull(sysHttpStreamMd5, sysHttpStreamMd5));
assertEquals(encryptionService.toHexString(compare), checkNotNull(sysHttpStreamMd5,
sysHttpStreamMd5));
assertEquals(((BufferLogger) wire.getWireLog()).buff.toString().getBytes().length, 3331484);
}
@ -169,9 +172,10 @@ public class WireLiveTest {
URLConnection connection = url.openConnection();
HttpWire wire = setUpSynch();
InputStream in = wire.input(connection.getInputStream());
byte[] compare = HttpUtils.md5(in);
byte[] compare = encryptionService.md5(in);
Thread.sleep(100);
assertEquals(HttpUtils.toHexString(compare), checkNotNull(sysHttpStreamMd5, sysHttpStreamMd5));
assertEquals(encryptionService.toHexString(compare), checkNotNull(sysHttpStreamMd5,
sysHttpStreamMd5));
assertEquals(((BufferLogger) wire.getWireLog()).buff.toString().getBytes().length, 3331484);
}

View File

@ -0,0 +1,148 @@
/**
*
* 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
* 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.util;
import static org.testng.Assert.assertEquals;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import org.jclouds.PerformanceTest;
import org.jclouds.util.internal.Base64;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* This tests the performance of Digest commands.
*
* @author Adrian Cole
*/
@Test(groups = "performance", sequential = true, testName = "jclouds.encryptionService")
public class EncryptionServiceTest extends PerformanceTest {
protected EncryptionService encryptionService;
@BeforeTest
protected void createEncryptionService() {
Injector i = Guice.createInjector();
encryptionService = i.getInstance(EncryptionService.class);
}
@Test(dataProvider = "hmacsha1")
void testDigestSerialResponseTime(byte[] key, String message, String base64Digest)
throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException {
for (int i = 0; i < 10000; i++)
testHmacSha1Base64(key, message, base64Digest);
}
@Test(dataProvider = "hmacsha1")
void testDigestParallelResponseTime(final byte[] key, final String message,
final String base64Digest) throws NoSuchProviderException, NoSuchAlgorithmException,
InvalidKeyException, InterruptedException, ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(exec);
for (int i = 0; i < 10000; i++)
completer.submit(new Callable<Boolean>() {
public Boolean call() throws Exception {
testHmacSha1Base64(key, message, base64Digest);
return true;
}
});
for (int i = 0; i < 10000; i++)
assert completer.take().get();
}
@DataProvider(name = "eTag")
public Object[][] createMD5Data() {
return base64MD5MessageDigest;
}
public final static Object[][] base64MD5MessageDigest = {
{ "apple", "1f3870be274f6c49b3e31a0c6728957f" },
{ "bear", "893b56e3cfe153fb770a120b83bac20c" },
{ "candy", "c48ba993d35c3abe0380f91738fe2a34" },
{ "dogma", "95eb470e4faee302e9cd3063b1923dab" },
{ "emma", "00a809937eddc44521da9521269e75c6" } };
public final static Object[][] base64KeyMessageDigest = {
{ Base64.decode("CwsLCwsLCwsLCwsLCwsLCwsLCws="), "Hi There",
"thcxhlUFcmTii8C2+zeMjvFGvgA=" },
{ Base64.decode("SmVmZQ=="), "what do ya want for nothing?",
"7/zfauXrL6LSdBbV8YTfnCWafHk=" },
{ Base64.decode("DAwMDAwMDAwMDAwMDAwMDAwMDAw="), "Test With Truncation",
"TBoDQktV4H/n8nvh1Yu5MkqaWgQ=" },
{
Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key - Hash Key First",
"qkrl4VJy0A6VcFY3zoo7Ve1AIRI=" },
{
Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
"6OmdD0UjfXhta7qnllx4CLv/GpE=" } };
@DataProvider(name = "hmacsha1")
public Object[][] createData1() {
return base64KeyMessageDigest;
}
@Test(dataProvider = "hmacsha1")
public void testHmacSha1Base64(byte[] key, String message, String base64Digest)
throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException {
String b64 = encryptionService.hmacSha1Base64(message, key);
assertEquals(b64, base64Digest);
}
@Test(dataProvider = "eTag")
public void testMD5Digest(String message, String base64Digest) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
String b64 = encryptionService.md5Hex(message.getBytes());
assertEquals(base64Digest, b64);
}
byte[] bytes = { 0, 1, 2, 4, 8, 16, 32, 64 };
String hex = "0001020408102040";
public void testHexStringEncode() throws UnsupportedEncodingException {
assertEquals(encryptionService.toHexString(bytes), hex);
}
public void testHexStringDecode() throws UnsupportedEncodingException {
assertEquals(encryptionService.fromHexString(hex), bytes);
}
public void testHexStringDecodeOx() throws UnsupportedEncodingException {
assertEquals(encryptionService.fromHexString("0x" + hex), bytes);
}
}

View File

@ -25,20 +25,10 @@ package org.jclouds.util;
import static org.testng.Assert.assertEquals;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import org.bouncycastle.util.encoders.Base64;
import org.jclouds.PerformanceTest;
import org.jclouds.http.HttpUtils;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
@ -101,92 +91,4 @@ public class HttpUtilsTest extends PerformanceTest {
.create("https://jclouds.blob.core.windows.net/jclouds-getpath/write-tests/file1%25.txt"));
}
@Test(dataProvider = "hmacsha1")
void testBouncyCastleDigestSerialResponseTime(byte[] key, String message, String base64Digest)
throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException {
for (int i = 0; i < 10000; i++)
testBouncyCastleHmacSha1Base64(key, message, base64Digest);
}
@Test(dataProvider = "hmacsha1")
void testBouncyCastleDigestParallelResponseTime(final byte[] key, final String message,
final String base64Digest) throws NoSuchProviderException, NoSuchAlgorithmException,
InvalidKeyException, InterruptedException, ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(exec);
for (int i = 0; i < 10000; i++)
completer.submit(new Callable<Boolean>() {
public Boolean call() throws Exception {
testBouncyCastleHmacSha1Base64(key, message, base64Digest);
return true;
}
});
for (int i = 0; i < 10000; i++)
assert completer.take().get();
}
@DataProvider(name = "eTag")
public Object[][] createMD5Data() {
return base64MD5MessageDigest;
}
public final static Object[][] base64MD5MessageDigest = {
{ "apple", "1f3870be274f6c49b3e31a0c6728957f" },
{ "bear", "893b56e3cfe153fb770a120b83bac20c" },
{ "candy", "c48ba993d35c3abe0380f91738fe2a34" },
{ "dogma", "95eb470e4faee302e9cd3063b1923dab" },
{ "emma", "00a809937eddc44521da9521269e75c6" } };
public final static Object[][] base64KeyMessageDigest = {
{ Base64.decode("CwsLCwsLCwsLCwsLCwsLCwsLCws="), "Hi There",
"thcxhlUFcmTii8C2+zeMjvFGvgA=" },
{ Base64.decode("SmVmZQ=="), "what do ya want for nothing?",
"7/zfauXrL6LSdBbV8YTfnCWafHk=" },
{ Base64.decode("DAwMDAwMDAwMDAwMDAwMDAwMDAw="), "Test With Truncation",
"TBoDQktV4H/n8nvh1Yu5MkqaWgQ=" },
{
Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key - Hash Key First",
"qkrl4VJy0A6VcFY3zoo7Ve1AIRI=" },
{
Base64
.decode("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo="),
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
"6OmdD0UjfXhta7qnllx4CLv/GpE=" } };
@DataProvider(name = "hmacsha1")
public Object[][] createData1() {
return base64KeyMessageDigest;
}
@Test(dataProvider = "hmacsha1")
public void testBouncyCastleHmacSha1Base64(byte[] key, String message, String base64Digest)
throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException {
String b64 = HttpUtils.hmacSha1Base64(message, key);
assertEquals(b64, base64Digest);
}
@Test(dataProvider = "eTag")
public void testBouncyCastleMD5Digest(String message, String base64Digest)
throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException,
UnsupportedEncodingException {
String b64 = HttpUtils.md5Hex(message.getBytes());
assertEquals(base64Digest, b64);
}
byte[] bytes = { 0, 1, 2, 4, 8, 16, 32, 64 };
String hex = "0001020408102040";
public void testHexStringEncode() throws UnsupportedEncodingException {
assertEquals(HttpUtils.toHexString(bytes), hex);
}
public void testHexStringDecode() throws UnsupportedEncodingException {
assertEquals(HttpUtils.fromHexString(hex), bytes);
}
public void testHexStringDecodeOx() throws UnsupportedEncodingException {
assertEquals(HttpUtils.fromHexString("0x" + hex), bytes);
}
}

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
$HeadURL$
$Revision$
$Date$
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
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.
====================================================================
-->
<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>
<artifactId>jclouds-extensions-project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>jclouds-bouncycastle</artifactId>
<name>jclouds bouncycastle EncryptionService Module</name>
<description>jclouds bouncycastle EncryptionService Module</description>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15</artifactId>
<version>1.44</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,120 @@
package org.jclouds.util.internal;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Base64;
import org.jclouds.util.Utils;
/**
*
* @author Adrian Cole
*/
public class BouncyCastleEncryptionService extends BaseEncryptionService {
public String hmacSha256Base64(String toEncode, byte[] key) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException {
Digest digest = new SHA256Digest();
return hmacBase64(toEncode, key, digest);
}
private String hmacBase64(String toEncode, byte[] key, Digest digest) {
byte[] resBuf = hmac(toEncode, key, digest);
return toBase64String(resBuf);
}
public byte[] hmac(String toEncode, byte[] key, Digest digest) {
HMac hmac = new HMac(digest);
byte[] resBuf = new byte[hmac.getMacSize()];
byte[] plainBytes = Utils.encodeString(toEncode);
byte[] keyBytes = key;
hmac.init(new KeyParameter(keyBytes));
hmac.update(plainBytes, 0, plainBytes.length);
hmac.doFinal(resBuf, 0);
return resBuf;
}
public String hmacSha1Base64(String toEncode, byte[] key) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException {
Digest digest = new SHA1Digest();
return hmacBase64(toEncode, key, digest);
}
public byte[] md5(byte[] plainBytes) {
MD5Digest eTag = new MD5Digest();
byte[] resBuf = new byte[eTag.getDigestSize()];
eTag.update(plainBytes, 0, plainBytes.length);
eTag.doFinal(resBuf, 0);
return resBuf;
}
public byte[] md5(File toEncode) {
MD5Digest eTag = new MD5Digest();
byte[] resBuf = new byte[eTag.getDigestSize()];
byte[] buffer = new byte[1024];
int numRead = -1;
InputStream i = null;
try {
i = new FileInputStream(toEncode);
do {
numRead = i.read(buffer);
if (numRead > 0) {
eTag.update(buffer, 0, numRead);
}
} while (numRead != -1);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(i);
}
eTag.doFinal(resBuf, 0);
return resBuf;
}
public String toBase64String(byte[] resBuf) {
return new String(Base64.encode(resBuf));
}
public MD5InputStreamResult generateMD5Result(InputStream toEncode) {
MD5Digest eTag = new MD5Digest();
byte[] resBuf = new byte[eTag.getDigestSize()];
byte[] buffer = new byte[1024];
ByteArrayOutputStream out = new ByteArrayOutputStream();
long length = 0;
int numRead = -1;
try {
do {
numRead = toEncode.read(buffer);
if (numRead > 0) {
length += numRead;
eTag.update(buffer, 0, numRead);
out.write(buffer, 0, numRead);
}
} while (numRead != -1);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(out);
IOUtils.closeQuietly(toEncode);
}
eTag.doFinal(resBuf, 0);
return new MD5InputStreamResult(out.toByteArray(), resBuf, length);
}
public byte[] fromBase64String(String encoded) {
return Base64.decode(encoded);
}
}

View File

@ -0,0 +1,90 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.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
* 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.util.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import org.bouncycastle.crypto.Digest;
/**
*
* @author Adrian Cole
*/
public interface EncryptionService {
String toHexString(byte[] raw);
byte[] fromHexString(String hex);
String hmacSha256Base64(String toEncode, byte[] key) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException;
byte[] hmac(String toEncode, byte[] key, Digest digest);
String hmacSha1Base64(String toEncode, byte[] key) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException;
String md5Hex(byte[] toEncode) throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException, UnsupportedEncodingException;
String md5Base64(byte[] toEncode) throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException;
byte[] md5(byte[] plainBytes);
byte[] md5(File toEncode);
String toBase64String(byte[] resBuf);
Long calculateSize(Object data);
byte[] md5(Object data);
MD5InputStreamResult generateMD5Result(InputStream toEncode);
public static class MD5InputStreamResult {
public final byte[] data;
public final byte[] md5;
public final long length;
MD5InputStreamResult(byte[] data, byte[] eTag, long length) {
this.data = checkNotNull(data, "data");
this.md5 = checkNotNull(eTag, "eTag");
checkArgument(length >= 0, "length cannot me negative");
this.length = length;
}
}
byte[] fromBase64String(String encoded);
}

View File

@ -0,0 +1,23 @@
package org.jclouds.util.internal;
import org.jclouds.util.EncryptionServiceTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* This tests the performance of Digest commands.
*
* @author Adrian Cole
*/
@Test(groups = "performance", sequential = true, testName = "jclouds.BouncyCastleEncryptionServiceTest")
public class BouncyCastleEncryptionServiceTest extends EncryptionServiceTest {
@BeforeTest
protected void createEncryptionService() {
Injector i = Guice.createInjector();
encryptionService = i.getInstance(BouncyCastleEncryptionService.class);
}
}

View File

@ -40,6 +40,7 @@
<module>gae</module>
<module>httpnio</module>
<module>joda</module>
<module>bouncycastle</module>
<module>log4j</module>
<module>ssh</module>
</modules>

View File

@ -54,6 +54,7 @@ import org.jclouds.mezeo.pcs2.handlers.PCSClientErrorRetryHandler;
import org.jclouds.mezeo.pcs2.reference.PCSConstants;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientFactory;
import org.jclouds.util.EncryptionService;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
@ -78,9 +79,9 @@ public class PCSRestClientModule extends AbstractModule {
@Singleton
public BasicAuthentication provideBasicAuthentication(
@Named(PCSConstants.PROPERTY_PCS2_USER) String user,
@Named(PCSConstants.PROPERTY_PCS2_PASSWORD) String password)
throws UnsupportedEncodingException {
return new BasicAuthentication(user, password);
@Named(PCSConstants.PROPERTY_PCS2_PASSWORD) String password,
EncryptionService encryptionService) throws UnsupportedEncodingException {
return new BasicAuthentication(user, password, encryptionService);
}
@Provides

View File

@ -59,6 +59,7 @@ import org.jclouds.mezeo.pcs2.xml.FileHandler;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.EncryptionService;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@ -303,9 +304,9 @@ public class PCSClientTest extends RestClientTest<PCSAsyncClient> {
@SuppressWarnings("unused")
@Provides
@Singleton
public BasicAuthentication provideBasicAuthentication()
public BasicAuthentication provideBasicAuthentication(EncryptionService encryptionService)
throws UnsupportedEncodingException {
return new BasicAuthentication("foo", "bar");
return new BasicAuthentication("foo", "bar", encryptionService);
}
};

View File

@ -41,6 +41,7 @@ import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.mezeo.pcs2.PCSCloud.Response;
import org.jclouds.rest.RestClientFactory;
import org.jclouds.rest.config.RestModule;
import org.jclouds.util.EncryptionService;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@ -94,9 +95,9 @@ public class PCSCloudLiveTest {
@SuppressWarnings("unused")
@Provides
@Singleton
public BasicAuthentication provideBasicAuthentication()
public BasicAuthentication provideBasicAuthentication(EncryptionService encryptionService)
throws UnsupportedEncodingException {
return new BasicAuthentication(user, password);
return new BasicAuthentication(user, password, encryptionService);
}
@SuppressWarnings("unused")

View File

@ -42,6 +42,7 @@ import org.jclouds.mezeo.pcs2.xml.CloudXlinkHandler;
import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.EncryptionService;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@ -66,7 +67,8 @@ public class PCSCloudTest {
assertEquals(httpMethod.getRequestLine(), "GET http://localhost:8080/ HTTP/1.1");
assertEquals(httpMethod.getHeaders().size(), 0);
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), ParseSax.class);
assertEquals(RestAnnotationProcessor.getSaxResponseParserClassOrNull(method), CloudXlinkHandler.class);
assertEquals(RestAnnotationProcessor.getSaxResponseParserClassOrNull(method),
CloudXlinkHandler.class);
assertEquals(httpMethod.getFilters().size(), 1);
assertEquals(httpMethod.getFilters().get(0).getClass(), BasicAuthentication.class);
assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null);
@ -92,9 +94,9 @@ public class PCSCloudTest {
@SuppressWarnings("unused")
@Provides
@Singleton
public BasicAuthentication provideBasicAuthentication()
public BasicAuthentication provideBasicAuthentication(EncryptionService encryptionService)
throws UnsupportedEncodingException {
return new BasicAuthentication("foo", "bar");
return new BasicAuthentication("foo", "bar", encryptionService);
}
}, new RestModule(), new ExecutorServiceModule(new WithinThreadExecutorService()),
new JavaUrlHttpCommandExecutorServiceModule());

View File

@ -34,9 +34,9 @@ import java.util.concurrent.TimeoutException;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.jclouds.http.HttpUtils;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.nirvanix.sdn.domain.UploadInfo;
import org.jclouds.util.internal.Base64;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
@ -85,7 +85,7 @@ public class SDNClientLiveTest {
connection.upload(uploadInfo.getHost(), uploadInfo.getToken(), containerName, blob);
Map<String, String> metadata = connection.getMetadata(containerName + "/test.txt");
assertEquals(metadata.get("MD5"), HttpUtils.toBase64String(md5));
assertEquals(metadata.get("MD5"), Base64.encodeBytes(md5));
String content = connection.getFile(containerName + "/test.txt");
assertEquals(content, "value");
@ -94,7 +94,7 @@ public class SDNClientLiveTest {
connection.setMetadata(containerName + "/test.txt", metadata);
metadata = connection.getMetadata(containerName + "/test.txt");
assertEquals(metadata.get("MD5"), HttpUtils.toBase64String(md5));
assertEquals(metadata.get("MD5"), Base64.encodeBytes(md5));
}
}

View File

@ -31,19 +31,22 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils;
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ObjectToBlob;
import org.jclouds.rackspace.cloudfiles.domain.CFObject;
import org.jclouds.rackspace.cloudfiles.reference.CloudFilesConstants;
import org.jclouds.util.EncryptionService;
public class BindCFObjectToEntity extends BindBlobToEntityAndUserMetadataToHeadersWithPrefix {
private final ObjectToBlob object2Blob;
private final EncryptionService encryptionService;
@Inject
public BindCFObjectToEntity(ObjectToBlob object2Blob,
@Named(CloudFilesConstants.PROPERTY_CLOUDFILES_METADATA_PREFIX) String prefix) {
super(prefix);
@Named(CloudFilesConstants.PROPERTY_CLOUDFILES_METADATA_PREFIX) String prefix,
EncryptionService encryptionService) {
super(prefix, encryptionService);
this.object2Blob = object2Blob;
this.encryptionService = encryptionService;
}
public void bindToRequest(HttpRequest request, Object entity) {
@ -60,7 +63,7 @@ public class BindCFObjectToEntity extends BindBlobToEntityAndUserMetadataToHeade
super.bindToRequest(request, object2Blob.apply(object));
if (object.getInfo().getHash() != null) {
request.getHeaders().put(HttpHeaders.ETAG,
HttpUtils.toHexString(object.getInfo().getHash()));
encryptionService.toHexString(object.getInfo().getHash()));
request.getHeaders().removeAll("Content-MD5");
}

View File

@ -30,9 +30,9 @@ import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.ResourceType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.blobstore.strategy.IsDirectoryStrategy;
import org.jclouds.http.HttpUtils;
import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata;
import org.jclouds.rackspace.cloudfiles.domain.ObjectInfo;
import org.jclouds.util.EncryptionService;
import com.google.common.base.Function;
@ -42,10 +42,13 @@ import com.google.common.base.Function;
@Singleton
public class ObjectToBlobMetadata implements Function<ObjectInfo, MutableBlobMetadata> {
private final IsDirectoryStrategy isDirectoryStrategy;
private final EncryptionService encryptionService;
@Inject
public ObjectToBlobMetadata(IsDirectoryStrategy isDirectoryStrategy) {
public ObjectToBlobMetadata(IsDirectoryStrategy isDirectoryStrategy,
EncryptionService encryptionService) {
this.isDirectoryStrategy = isDirectoryStrategy;
this.encryptionService = encryptionService;
}
public MutableBlobMetadata apply(ObjectInfo from) {
@ -54,7 +57,7 @@ public class ObjectToBlobMetadata implements Function<ObjectInfo, MutableBlobMet
if (from.getContentType() != null)
to.setContentType(from.getContentType());
if (from.getHash() != null)
to.setETag(HttpUtils.toHexString(from.getHash()));
to.setETag(encryptionService.toHexString(from.getHash()));
to.setName(from.getName());
if (from.getBytes() != null)
to.setSize(from.getBytes());

View File

@ -23,14 +23,15 @@
*/
package org.jclouds.rackspace.cloudfiles.blobstore.functions;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.domain.ResourceType;
import org.jclouds.http.HttpUtils;
import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata;
import org.jclouds.rackspace.cloudfiles.domain.internal.MutableObjectInfoWithMetadataImpl;
import org.jclouds.util.EncryptionService;
import com.google.common.base.Function;
@ -38,17 +39,25 @@ import com.google.common.base.Function;
* @author Adrian Cole
*/
@Singleton
public class ResourceToObjectInfo implements Function<ResourceMetadata, MutableObjectInfoWithMetadata> {
public class ResourceToObjectInfo implements
Function<ResourceMetadata, MutableObjectInfoWithMetadata> {
private final EncryptionService encryptionService;
@Inject
public ResourceToObjectInfo(EncryptionService encryptionService) {
this.encryptionService = encryptionService;
}
public MutableObjectInfoWithMetadata apply(ResourceMetadata base) {
MutableObjectInfoWithMetadata to = new MutableObjectInfoWithMetadataImpl();
if (base.getType() == ResourceType.BLOB){
to.setContentType(((BlobMetadata)base).getContentType());
to.setHash(((BlobMetadata)base).getContentMD5());
} else if (base.getType() == ResourceType.RELATIVE_PATH){
if (base.getType() == ResourceType.BLOB) {
to.setContentType(((BlobMetadata) base).getContentType());
to.setHash(((BlobMetadata) base).getContentMD5());
} else if (base.getType() == ResourceType.RELATIVE_PATH) {
to.setContentType("application/directory");
}
if (base.getETag() != null && to.getHash() == null)
to.setHash(HttpUtils.fromHexString(base.getETag()));
to.setHash(encryptionService.fromHexString(base.getETag()));
to.setName(base.getName());
to.setLastModified(base.getLastModified());
if (base.getSize() != null)

View File

@ -28,11 +28,11 @@ import javax.inject.Inject;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ResourceToObjectInfo;
import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.EncryptionService;
import com.google.common.base.Function;
@ -45,12 +45,14 @@ public class ParseObjectInfoFromHeaders implements
Function<HttpResponse, MutableObjectInfoWithMetadata>, InvocationContext {
private final ParseSystemAndUserMetadataFromHeaders blobMetadataParser;
private final ResourceToObjectInfo blobToObjectInfo;
private final EncryptionService encryptionService;
@Inject
public ParseObjectInfoFromHeaders(ParseSystemAndUserMetadataFromHeaders blobMetadataParser,
ResourceToObjectInfo blobToObjectInfo) {
ResourceToObjectInfo blobToObjectInfo, EncryptionService encryptionService) {
this.blobMetadataParser = blobMetadataParser;
this.blobToObjectInfo = blobToObjectInfo;
this.encryptionService = encryptionService;
}
/**
@ -61,7 +63,7 @@ public class ParseObjectInfoFromHeaders implements
MutableObjectInfoWithMetadata to = blobToObjectInfo.apply(base);
String eTagHeader = from.getFirstHeaderOrNull("Etag");
if (eTagHeader != null) {
to.setHash(HttpUtils.fromHexString(eTagHeader.replaceAll("\"", "")));
to.setHash(encryptionService.fromHexString(eTagHeader.replaceAll("\"", "")));
}
return to;
}

View File

@ -37,12 +37,12 @@ import javax.inject.Inject;
import org.jclouds.blobstore.domain.ListContainerResponse;
import org.jclouds.blobstore.domain.internal.ListContainerResponseImpl;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.rackspace.cloudfiles.domain.ObjectInfo;
import org.jclouds.rackspace.cloudfiles.options.ListContainerOptions;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.EncryptionService;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
@ -59,10 +59,12 @@ public class ParseObjectInfoListFromJsonResponse extends
ParseJson<ListContainerResponse<ObjectInfo>> implements InvocationContext {
private GeneratedHttpRequest<?> request;
private static EncryptionService encryptionService;
@Inject
public ParseObjectInfoListFromJsonResponse(Gson gson) {
public ParseObjectInfoListFromJsonResponse(Gson gson, EncryptionService encryptionService) {
super(gson);
ParseObjectInfoListFromJsonResponse.encryptionService = encryptionService;
}
public static class ObjectInfoImpl implements ObjectInfo {
@ -85,7 +87,7 @@ public class ParseObjectInfoListFromJsonResponse extends
}
public byte[] getHash() {
return HttpUtils.fromHexString(hash);
return encryptionService.fromHexString(hash);
}
public Date getLastModified() {

View File

@ -33,9 +33,9 @@ import java.util.Map;
import java.util.Map.Entry;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils;
import org.jclouds.rackspace.cloudservers.domain.Addresses;
import org.jclouds.rest.binders.BindToJsonEntity;
import org.jclouds.util.internal.Base64;
import com.google.common.collect.ImmutableMap;
import com.google.inject.internal.Lists;
@ -54,7 +54,7 @@ public class CreateServerOptions extends BindToJsonEntity {
public File(String path, byte[] contents) {
this.path = checkNotNull(path, "path");
this.contents = HttpUtils.toBase64String(checkNotNull(contents, "contents"));
this.contents = Base64.encodeBytes(checkNotNull(contents, "contents"));
checkArgument(path.getBytes().length < 255, String.format(
"maximum length of path is 255 bytes. Path specified %s is %d bytes", path, path
.getBytes().length));

View File

@ -44,7 +44,6 @@ import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.ListResponse;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.options.GetOptions;
import org.jclouds.rackspace.cloudfiles.domain.AccountMetadata;
import org.jclouds.rackspace.cloudfiles.domain.CFObject;
@ -54,6 +53,8 @@ import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata;
import org.jclouds.rackspace.cloudfiles.domain.ObjectInfo;
import org.jclouds.rackspace.cloudfiles.options.ListCdnContainerOptions;
import org.jclouds.rackspace.cloudfiles.options.ListContainerOptions;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.internal.JCEEncryptionService;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
@ -68,6 +69,7 @@ import com.google.common.collect.Maps;
@Test(groups = "live", testName = "cloudfiles.CloudFilesClientLiveTest")
public class CloudFilesClientLiveTest extends
BaseBlobStoreIntegrationTest<CloudFilesAsyncClient, CloudFilesClient> {
private static final EncryptionService encryptionService = new JCEEncryptionService();
/**
* this method overrides containerName to ensure it isn't found
@ -170,7 +172,7 @@ public class CloudFilesClientLiveTest extends
assertTrue(context.getApi().disableCDN(containerNameWithCDN));
cdnMetadata = context.getApi().getCDNMetadata(containerNameWithCDN);
assertEquals(cdnMetadata.isCDNEnabled(), false);
assertEquals(cdnMetadata.isCDNEnabled(), false);
} finally {
recycleContainer(containerNameWithCDN);
recycleContainer(containerNameWithoutCDN);
@ -307,7 +309,8 @@ public class CloudFilesClientLiveTest extends
CFObject object = newCFObject(data, key);
byte[] md5 = object.getInfo().getHash();
String newEtag = context.getApi().putObject(containerName, object);
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(object.getInfo().getHash()));
assertEquals(encryptionService.toHexString(md5), encryptionService.toHexString(object
.getInfo().getHash()));
// Test HEAD of missing object
try {
@ -322,8 +325,9 @@ public class CloudFilesClientLiveTest extends
// TODO assertEquals(metadata.getName(), object.getMetadata().getName());
assertEquals(metadata.getBytes(), new Long(data.length()));
assertEquals(metadata.getContentType(), "text/plain");
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(object.getInfo().getHash()));
assertEquals(metadata.getHash(), HttpUtils.fromHexString(newEtag));
assertEquals(encryptionService.toHexString(md5), encryptionService.toHexString(object
.getInfo().getHash()));
assertEquals(metadata.getHash(), encryptionService.fromHexString(newEtag));
assertEquals(metadata.getMetadata().entrySet().size(), 1);
assertEquals(metadata.getMetadata().get("metadata"), "metadata-value");
@ -346,9 +350,9 @@ public class CloudFilesClientLiveTest extends
// TODO assertEquals(getBlob.getName(), object.getMetadata().getName());
assertEquals(getBlob.getContentLength(), new Long(data.length()));
assertEquals(getBlob.getInfo().getContentType(), "text/plain");
assertEquals(HttpUtils.toHexString(md5), HttpUtils
.toHexString(getBlob.getInfo().getHash()));
assertEquals(HttpUtils.fromHexString(newEtag), getBlob.getInfo().getHash());
assertEquals(encryptionService.toHexString(md5), encryptionService.toHexString(getBlob
.getInfo().getHash()));
assertEquals(encryptionService.fromHexString(newEtag), getBlob.getInfo().getHash());
assertEquals(getBlob.getInfo().getMetadata().entrySet().size(), 2);
assertEquals(getBlob.getInfo().getMetadata().get("new-metadata-1"), "value-1");
assertEquals(getBlob.getInfo().getMetadata().get("new-metadata-2"), "value-2");
@ -356,7 +360,7 @@ public class CloudFilesClientLiveTest extends
// Test PUT with invalid ETag (as if object's data was corrupted in transit)
String correctEtag = newEtag;
String incorrectEtag = "0" + correctEtag.substring(1);
object.getInfo().setHash(HttpUtils.fromHexString(incorrectEtag));
object.getInfo().setHash(encryptionService.fromHexString(incorrectEtag));
try {
context.getApi().putObject(containerName, object);
} catch (HttpResponseException e) {
@ -369,8 +373,8 @@ public class CloudFilesClientLiveTest extends
blob.getInfo().setName("chunked-object");
blob.setData(bais);
newEtag = context.getApi().putObject(containerName, blob);
assertEquals(HttpUtils.toHexString(md5), HttpUtils
.toHexString(getBlob.getInfo().getHash()));
assertEquals(encryptionService.toHexString(md5), encryptionService.toHexString(getBlob
.getInfo().getHash()));
// Test GET with options
// Non-matching ETag
@ -384,7 +388,7 @@ public class CloudFilesClientLiveTest extends
// Matching ETag
getBlob = context.getApi().getObject(containerName, object.getInfo().getName(),
GetOptions.Builder.ifETagMatches(newEtag));
assertEquals(getBlob.getInfo().getHash(), HttpUtils.fromHexString(newEtag));
assertEquals(getBlob.getInfo().getHash(), encryptionService.fromHexString(newEtag));
getBlob = context.getApi().getObject(containerName, object.getInfo().getName(),
GetOptions.Builder.startAt(8));
assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data.substring(8));

View File

@ -23,45 +23,50 @@
*/
package org.jclouds.rimuhosting.miro;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import javax.inject.Singleton;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import static org.testng.Assert.assertEquals;
import org.jclouds.util.EncryptionService;
import org.testng.annotations.Test;
import javax.inject.Singleton;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/**
* Tests annotation parsing of {@code RimuHostingAsyncClient}
*
*
* @author Ivan Meredith
*/
@Test(groups = "unit", testName = "rimuhosting.RimuHostingAsyncClientTest")
public class RimuHostingAsyncClientTest extends RestClientTest<RimuHostingAsyncClient> {
public void testGetMyMentions() throws SecurityException, NoSuchMethodException, IOException {
/* Method method = RimuHostingAsyncClient.class.getMethod("TODO: insert test method name");
GeneratedHttpRequest<RimuHostingAsyncClient> httpMethod = processor.createRequest(method);
assertRequestLineEquals(httpMethod, "TODO: insert expected request");
assertHeadersEqual(httpMethod, "");
assertEntityEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseStatusesFromJsonResponse.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);*/
/*
* Method method = RimuHostingAsyncClient.class.getMethod("TODO: insert test method name");
* GeneratedHttpRequest<RimuHostingAsyncClient> httpMethod = processor.createRequest(method);
*
* assertRequestLineEquals(httpMethod, "TODO: insert expected request");
* assertHeadersEqual(httpMethod, ""); assertEntityEquals(httpMethod, null);
*
* assertResponseParserClassEquals(method, httpMethod, ParseStatusesFromJsonResponse.class);
* assertSaxResponseParserClassEquals(method, null); assertExceptionParserClassEquals(method,
* null);
*
* checkFilters(httpMethod);
*/
}
@Override
@ -82,7 +87,7 @@ public class RimuHostingAsyncClientTest extends RestClientTest<RimuHostingAsyncC
@Override
protected void configure() {
bind(URI.class).annotatedWith(RimuHosting.class).toInstance(
URI.create("https://rimuhosting.com/r"));
URI.create("https://rimuhosting.com/r"));
bind(Logger.LoggerFactory.class).toInstance(new LoggerFactory() {
public Logger getLogger(String category) {
return Logger.NULL;
@ -93,9 +98,9 @@ public class RimuHostingAsyncClientTest extends RestClientTest<RimuHostingAsyncC
@SuppressWarnings("unused")
@Provides
@Singleton
public BasicAuthentication provideBasicAuthentication()
throws UnsupportedEncodingException {
return new BasicAuthentication("foo", "bar");
public BasicAuthentication provideBasicAuthentication(EncryptionService encryptionService)
throws UnsupportedEncodingException {
return new BasicAuthentication("foo", "bar", encryptionService);
}
};

View File

@ -38,6 +38,7 @@ import org.jclouds.twitter.Twitter;
import org.jclouds.twitter.TwitterAsyncClient;
import org.jclouds.twitter.TwitterClient;
import org.jclouds.twitter.reference.TwitterConstants;
import org.jclouds.util.EncryptionService;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
@ -61,9 +62,9 @@ public class TwitterRestClientModule extends AbstractModule {
@Singleton
public BasicAuthentication provideBasicAuthentication(
@Named(TwitterConstants.PROPERTY_TWITTER_USER) String user,
@Named(TwitterConstants.PROPERTY_TWITTER_PASSWORD) String password)
throws UnsupportedEncodingException {
return new BasicAuthentication(user, password);
@Named(TwitterConstants.PROPERTY_TWITTER_PASSWORD) String password,
EncryptionService encryptionService) throws UnsupportedEncodingException {
return new BasicAuthentication(user, password, encryptionService);
}
@Provides

View File

@ -39,6 +39,7 @@ import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.twitter.functions.ParseStatusesFromJsonResponse;
import org.jclouds.util.EncryptionService;
import org.testng.annotations.Test;
import com.google.inject.AbstractModule;
@ -98,9 +99,9 @@ public class TwitterClientTest extends RestClientTest<TwitterAsyncClient> {
@SuppressWarnings("unused")
@Provides
@Singleton
public BasicAuthentication provideBasicAuthentication()
public BasicAuthentication provideBasicAuthentication(EncryptionService encryptionService)
throws UnsupportedEncodingException {
return new BasicAuthentication("foo", "bar");
return new BasicAuthentication("foo", "bar", encryptionService);
}
};

View File

@ -43,6 +43,7 @@ import org.jclouds.http.RequiresHttp;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientFactory;
import org.jclouds.util.EncryptionService;
import org.jclouds.util.Utils;
import org.jclouds.vcloud.VCloudDiscovery;
import org.jclouds.vcloud.VCloudLogin;
@ -147,8 +148,9 @@ public class VCloudDiscoveryRestClientModule extends AbstractModule {
@Provides
@Singleton
public BasicAuthentication provideBasicAuthentication(@Named(PROPERTY_VCLOUD_USER) String user,
@Named(PROPERTY_VCLOUD_KEY) String key) throws UnsupportedEncodingException {
return new BasicAuthentication(user, key);
@Named(PROPERTY_VCLOUD_KEY) String key, EncryptionService encryptionService)
throws UnsupportedEncodingException {
return new BasicAuthentication(user, key, encryptionService);
}
}

View File

@ -38,6 +38,7 @@ import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.internal.JCEEncryptionService;
import org.jclouds.vcloud.functions.ParseLoginResponseFromHeaders;
import org.testng.annotations.Test;
@ -58,7 +59,8 @@ public class VCloudLoginTest extends RestClientTest<VCloudLogin> {
GeneratedHttpRequest<VCloudLogin> httpMethod = processor.createRequest(method);
assertEquals(httpMethod.getRequestLine(), "POST http://localhost:8080/login HTTP/1.1");
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT + ": application/vnd.vmware.vcloud.organizationList+xml\n");
assertHeadersEqual(httpMethod, HttpHeaders.ACCEPT
+ ": application/vnd.vmware.vcloud.organizationList+xml\n");
assertEntityEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseLoginResponseFromHeaders.class);
@ -88,7 +90,8 @@ public class VCloudLoginTest extends RestClientTest<VCloudLogin> {
bind(URI.class).annotatedWith(org.jclouds.vcloud.endpoints.VCloudLogin.class)
.toInstance(URI.create("http://localhost:8080/login"));
try {
bind(BasicAuthentication.class).toInstance(new BasicAuthentication("user", "pass"));
bind(BasicAuthentication.class).toInstance(
new BasicAuthentication("user", "pass", new JCEEncryptionService()));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}