Issue 86 updated to latest azure api release and added more support for queue

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2674 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2010-01-19 11:34:28 +00:00
parent e38f58902c
commit 0f6412dfbd
59 changed files with 1165 additions and 679 deletions

View File

@ -42,8 +42,8 @@ import org.jclouds.azure.storage.blob.options.CreateContainerOptions;
import org.jclouds.azure.storage.blob.options.ListBlobsOptions;
import org.jclouds.azure.storage.blob.xml.AccountNameEnumerationResultsHandler;
import org.jclouds.azure.storage.blob.xml.ContainerNameEnumerationResultsHandler;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.reference.AzureStorageHeaders;
import org.jclouds.blobstore.attr.ConsistencyModel;
@ -80,8 +80,8 @@ import com.google.common.util.concurrent.ListenableFuture;
* @author Adrian Cole
*/
@SkipEncoding('/')
@RequestFilters(SharedKeyAuthentication.class)
@Headers(keys = AzureStorageHeaders.VERSION, values = "2009-07-17")
@RequestFilters(SharedKeyLiteAuthentication.class)
@Headers(keys = AzureStorageHeaders.VERSION, values = "2009-09-19")
@Endpoint(AzureBlob.class)
@ConsistencyModel(ConsistencyModels.STRICT)
public interface AzureBlobAsyncClient {
@ -95,7 +95,7 @@ public interface AzureBlobAsyncClient {
@XMLResponseParser(AccountNameEnumerationResultsHandler.class)
@Path("/")
@QueryParams(keys = "comp", values = "list")
ListenableFuture<? extends BoundedSortedSet<ListableContainerProperties>> listContainers(
ListenableFuture<? extends BoundedSet<ListableContainerProperties>> listContainers(
ListOptions... listOptions);
/**
@ -161,7 +161,7 @@ public interface AzureBlobAsyncClient {
@Path("$root")
@ExceptionParser(ReturnTrueOn404.class)
@QueryParams(keys = "restype", values = "container")
ListenableFuture<Boolean> deleteRootContainer();
ListenableFuture<Void> deleteRootContainer();
/**
* @see AzureBlobClient#listBlobs(String, ListBlobsOptions)

View File

@ -27,7 +27,7 @@ import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableContainerProperties;
import org.jclouds.azure.storage.blob.options.CreateContainerOptions;
import org.jclouds.azure.storage.blob.options.ListBlobsOptions;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.concurrent.Timeout;
import org.jclouds.http.options.GetOptions;
@ -57,7 +57,7 @@ public interface AzureBlobClient {
* controls the number or type of results requested
* @see ListOptions
*/
BoundedSortedSet<ListableContainerProperties> listContainers(ListOptions... listOptions);
BoundedSet<ListableContainerProperties> listContainers(ListOptions... listOptions);
/**
* The Create Container operation creates a new container under the specified account. If the
@ -138,7 +138,7 @@ public interface AzureBlobClient {
* @see deleteContainer(String)
* @see createRootContainer(CreateContainerOptions)
*/
boolean deleteRootContainer();
void deleteRootContainer();
/**
* The List Blobs operation enumerates the list of blobs under the specified container.

View File

@ -40,13 +40,18 @@ import com.google.inject.Module;
* @see AzureBlobAsyncClient
*/
public class AzureBlobContextFactory {
public static RestContext<AzureBlobAsyncClient, AzureBlobClient> createContext(
Properties properties, Module... modules) {
return new AzureBlobContextBuilder(new AzureBlobPropertiesBuilder(properties).build())
.withModules(modules).buildContext();
}
public static RestContext<AzureBlobAsyncClient, AzureBlobClient> createContext(
Properties properties, String account, String encodedKey, Module... modules) {
return new AzureBlobContextBuilder(new AzureBlobPropertiesBuilder(properties)
.withCredentials(account, encodedKey).build()).withModules(modules).buildContext();
}
public static RestContext<AzureBlobAsyncClient, AzureBlobClient> createContext(String account,
String encodedKey, Module... modules) {
return new AzureBlobContextBuilder(new AzureBlobPropertiesBuilder(account, encodedKey)

View File

@ -24,7 +24,7 @@ import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
import org.jclouds.azure.storage.reference.AzureStorageHeaders;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseContentMD5FromHeaders;
@ -43,7 +43,7 @@ import org.jclouds.rest.annotations.SkipEncoding;
* @author Adrian Cole
*/
@SkipEncoding('/')
@RequestFilters(SharedKeyAuthentication.class)
@RequestFilters(SharedKeyLiteAuthentication.class)
@Headers(keys = AzureStorageHeaders.VERSION, values = "2009-07-17")
public interface AzureBlobUtil {

View File

@ -23,35 +23,64 @@ import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.azure.storage.blob.blobstore.functions.AzureBlobToBlob;
import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.azure.storage.blob.reference.AzureBlobConstants;
import org.jclouds.blobstore.binders.BindBlobToPayloadAndUserMetadataToHeadersWithPrefix;
import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
public class BindAzureBlobToPayload extends BindBlobToPayloadAndUserMetadataToHeadersWithPrefix {
@Singleton
public class BindAzureBlobToPayload implements Binder {
private final AzureBlobToBlob azureBlob2Blob;
private final String metadataPrefix;
private final EncryptionService encryptionService;
@Inject
public BindAzureBlobToPayload(AzureBlobToBlob azureBlob2Blob,
public BindAzureBlobToPayload(
@Named(AzureBlobConstants.PROPERTY_AZUREBLOB_METADATA_PREFIX) String prefix,
EncryptionService encryptionService) {
super(prefix, encryptionService);
this.azureBlob2Blob = azureBlob2Blob;
this.metadataPrefix = prefix;
this.encryptionService = encryptionService;
}
public void bindToRequest(HttpRequest request, Object payload) {
AzureBlob object = (AzureBlob) payload;
checkArgument(object.getProperties().getSize() >= 0, "size must be set");
checkArgument(
checkNotNull(object.getContentLength(), "object.getContentLength()") <= 64 * 1024 * 1024,
"maximum size for put Blob is 64MB");
super.bindToRequest(request, azureBlob2Blob.apply(object));
checkArgument(object.getProperties().getContentLength() >= 0, "size must be set");
request.getHeaders().put("x-ms-blob-type", object.getProperties().getType().toString());
switch (object.getProperties().getType()) {
case PAGE_BLOB:
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, "0");
request.getHeaders().put("x-ms-blob-content-length", object.getContentLength() + "");
break;
case BLOCK_BLOB:
checkArgument(
checkNotNull(object.getContentLength(), "object.getContentLength()") <= 64 * 1024 * 1024,
"maximum size for put Blob is 64MB");
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, object.getContentLength() + "");
break;
}
for (String key : object.getProperties().getMetadata().keySet()) {
request.getHeaders().put(key.startsWith(metadataPrefix) ? key : metadataPrefix + key,
object.getProperties().getMetadata().get(key));
}
request.setPayload(checkNotNull(object.getContent(), "object.getContent()"));
request.getHeaders().put(
HttpHeaders.CONTENT_TYPE,
checkNotNull(object.getProperties().getContentType(),
"object.metadata.contentType()"));
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, object.getContentLength() + "");
if (object.getProperties().getContentMD5() != null) {
request.getHeaders().put("Content-MD5",
encryptionService.toBase64String(object.getProperties().getContentMD5()));
}
if (object.getProperties().getContentLanguage() != null) {
request.getHeaders().put(HttpHeaders.CONTENT_LANGUAGE,
object.getProperties().getContentLanguage());

View File

@ -22,7 +22,7 @@ import static com.google.common.util.concurrent.Futures.compose;
import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
import static org.jclouds.concurrent.internal.ConcurrentUtils.makeListenable;
import java.util.SortedSet;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
@ -135,9 +135,9 @@ public class AzureAsyncBlobStore extends BaseAzureBlobStore implements AsyncBlob
public ListenableFuture<? extends org.jclouds.blobstore.domain.ListResponse<? extends StorageMetadata>> list() {
return compose(
async.listContainers(),
new Function<SortedSet<ListableContainerProperties>, org.jclouds.blobstore.domain.ListResponse<? extends StorageMetadata>>() {
new Function<Set<ListableContainerProperties>, org.jclouds.blobstore.domain.ListResponse<? extends StorageMetadata>>() {
public org.jclouds.blobstore.domain.ListResponse<? extends StorageMetadata> apply(
SortedSet<ListableContainerProperties> from) {
Set<ListableContainerProperties> from) {
return new ListResponseImpl<StorageMetadata>(Iterables.transform(from,
container2ResourceMd), null, null, false);
}

View File

@ -20,7 +20,7 @@ package org.jclouds.azure.storage.blob.blobstore;
import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
import java.util.SortedSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
@ -121,9 +121,9 @@ public class AzureBlobStore extends BaseAzureBlobStore implements BlobStore {
}
public ListResponse<? extends StorageMetadata> list() {
return new Function<SortedSet<ListableContainerProperties>, org.jclouds.blobstore.domain.ListResponse<? extends StorageMetadata>>() {
return new Function<Set<ListableContainerProperties>, org.jclouds.blobstore.domain.ListResponse<? extends StorageMetadata>>() {
public org.jclouds.blobstore.domain.ListResponse<? extends StorageMetadata> apply(
SortedSet<ListableContainerProperties> from) {
Set<ListableContainerProperties> from) {
return new ListResponseImpl<StorageMetadata>(Iterables.transform(from,
container2ResourceMd), null, null, false);
}

View File

@ -39,7 +39,7 @@ public class BlobMetadataToBlobProperties implements Function<BlobMetadata, Muta
to.setName(base.getName());
to.setLastModified(base.getLastModified());
if (base.getSize() != null)
to.setSize(base.getSize());
to.setContentLength(base.getSize());
if (base.getUserMetadata() != null)
to.setMetadata(base.getUserMetadata());
return to;

View File

@ -23,24 +23,39 @@ import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.blobstore.strategy.IsDirectoryStrategy;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class BlobPropertiesToBlobMetadata extends
ListableBlobPropertiesToBlobMetadata<BlobProperties> {
public class BlobPropertiesToBlobMetadata implements Function<BlobProperties, MutableBlobMetadata> {
private final IsDirectoryStrategy isDirectoryStrategy;
@Inject
public BlobPropertiesToBlobMetadata(IsDirectoryStrategy isDirectoryStrategy) {
super(isDirectoryStrategy);
this.isDirectoryStrategy = isDirectoryStrategy;
}
@Override
public MutableBlobMetadata apply(BlobProperties from) {
MutableBlobMetadata to = super.apply(from);
to.setContentMD5(from.getContentMD5());
MutableBlobMetadata to = new MutableBlobMetadataImpl();
if (from.getContentMD5() != null)
to.setContentMD5(from.getContentMD5());
if (from.getContentType() != null)
to.setContentType(from.getContentType());
to.setUserMetadata(from.getMetadata());
to.setETag(from.getETag());
to.setLastModified(from.getLastModified());
to.setName(from.getName());
to.setSize(from.getContentLength());
to.setType(StorageType.BLOB);
if (isDirectoryStrategy.execute(to)) {
to.setType(StorageType.RELATIVE_PATH);
}
return to;
}
}

View File

@ -24,7 +24,6 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableBlobProperties;
import org.jclouds.blobstore.domain.ListContainerResponse;
import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.internal.ListContainerResponseImpl;
@ -39,12 +38,11 @@ import com.google.common.collect.Sets;
@Singleton
public class ListBlobsResponseToResourceList implements
Function<ListBlobsResponse, ListContainerResponse<? extends StorageMetadata>> {
private final ListableBlobPropertiesToBlobMetadata<ListableBlobProperties> object2blobMd;
private final BlobPropertiesToBlobMetadata object2blobMd;
private final CommonPrefixesToResourceMetadata prefix2ResourceMd;
@Inject
public ListBlobsResponseToResourceList(
ListableBlobPropertiesToBlobMetadata<ListableBlobProperties> object2blobMd,
public ListBlobsResponseToResourceList(BlobPropertiesToBlobMetadata object2blobMd,
CommonPrefixesToResourceMetadata prefix2ResourceMd) {
this.object2blobMd = object2blobMd;
this.prefix2ResourceMd = prefix2ResourceMd;
@ -53,8 +51,8 @@ public class ListBlobsResponseToResourceList implements
public ListContainerResponse<? extends StorageMetadata> apply(ListBlobsResponse from) {
SortedSet<StorageMetadata> contents = Sets.newTreeSet(Iterables.concat(Iterables.transform(
from, object2blobMd), prefix2ResourceMd.apply(from.getBlobPrefixes())));
return new ListContainerResponseImpl<StorageMetadata>(contents, from.getPrefix(), from.getMarker(),
from.getMaxResults(), from.size() == from.getMaxResults());
return new ListContainerResponseImpl<StorageMetadata>(contents, from.getPrefix(), from
.getMarker(), from.getMaxResults(), from.size() == from.getMaxResults());
}
}

View File

@ -1,59 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.functions;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.domain.ListableBlobProperties;
import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.blobstore.strategy.IsDirectoryStrategy;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class ListableBlobPropertiesToBlobMetadata<T extends ListableBlobProperties> implements
Function<T, MutableBlobMetadata> {
private final IsDirectoryStrategy isDirectoryStrategy;
@Inject
public ListableBlobPropertiesToBlobMetadata(IsDirectoryStrategy isDirectoryStrategy) {
this.isDirectoryStrategy = isDirectoryStrategy;
}
public MutableBlobMetadata apply(T from) {
MutableBlobMetadata to = new MutableBlobMetadataImpl();
if (from.getContentType() != null)
to.setContentType(from.getContentType());
to.setETag(from.getETag());
to.setLastModified(from.getLastModified());
to.setName(from.getName());
to.setSize(from.getSize());
to.setType(StorageType.BLOB);
if (isDirectoryStrategy.execute(to)) {
to.setType(StorageType.RELATIVE_PATH);
}
return to;
}
}

View File

@ -23,10 +23,10 @@ import java.util.SortedSet;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableBlobProperties;
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
import org.jclouds.azure.storage.blob.domain.internal.TreeSetListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.internal.HashSetListBlobsResponse;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ListContainerResponse;
import org.jclouds.blobstore.domain.StorageMetadata;
@ -52,14 +52,14 @@ public class ResourceToListBlobsResponse implements
public ListBlobsResponse apply(ListContainerResponse<? extends StorageMetadata> list) {
Iterable<ListableBlobProperties> contents = Iterables.transform(Iterables.filter(list,
Iterable<BlobProperties> contents = Iterables.transform(Iterables.filter(list,
new Predicate<StorageMetadata>() {
public boolean apply(StorageMetadata input) {
return input.getType() == StorageType.BLOB;
}
}), new Function<StorageMetadata, ListableBlobProperties>() {
}), new Function<StorageMetadata, BlobProperties>() {
public MutableBlobProperties apply(StorageMetadata from) {
return blob2ObjectMd.apply((BlobMetadata) from);
@ -81,7 +81,7 @@ public class ResourceToListBlobsResponse implements
}
}));
return new TreeSetListBlobsResponse(contents, null, list.getPath(), null, list
.getMaxResults(),list.getMarker(), "/", commonPrefixes);
return new HashSetListBlobsResponse(contents, null, list.getPath(), null, list
.getMaxResults(), list.getMarker(), "/", commonPrefixes);
}
}

View File

@ -18,10 +18,12 @@
*/
package org.jclouds.azure.storage.blob.domain;
import javax.annotation.Nullable;
import org.jclouds.http.PayloadEnclosing;
import com.google.common.collect.Multimap;
import com.google.inject.internal.Nullable;
/**
* Amazon S3 is designed to store objects. Objects are stored in buckets and consist of a
@ -33,6 +35,8 @@ import com.google.inject.internal.Nullable;
* />
*/
public interface AzureBlob extends PayloadEnclosing, Comparable<AzureBlob> {
public interface Factory {
AzureBlob create(@Nullable MutableBlobProperties properties);
}

View File

@ -18,6 +18,8 @@
*/
package org.jclouds.azure.storage.blob.domain;
import java.net.URI;
import java.util.Date;
import java.util.Map;
/**
@ -25,15 +27,48 @@ import java.util.Map;
* @author Adrian Cole
*
*/
public interface BlobProperties extends ListableBlobProperties {
/**
* This value present in system metadata requests on blobs which were created specifying the
* Content-MD5 header. It is not present in container listings.
*/
byte[] getContentMD5();
public interface BlobProperties extends Comparable<BlobProperties> {
Map<String, String> getMetadata();
/**
*
*/
BlobType getType();
URI getUrl();
String getName();
Date getLastModified();
String getETag();
Long getContentLength();
/**
* This value present in system metadata requests on blobs which were created specifying the
* Content-MD5 header.
*/
byte[] getContentMD5();
/**
*
* A standard MIME type describing the format of the contents. If none is provided, the default
* is binary/octet-stream.
*
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17"/>
*/
String getContentType();
/**
* Specifies what content encodings have been applied to the object and thus what decoding
* mechanisms must be applied in order to obtain the media-type referenced by the Content-Type
* header field.
*
* @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.11" />
*/
public String getContentEncoding();
public String getContentLanguage();
}

View File

@ -0,0 +1,44 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.CaseFormat;
/**
* @author Adrian Cole
*/
public enum BlobType {
BLOCK_BLOB, PAGE_BLOB;
public String value() {
return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()));
}
@Override
public String toString() {
return value();
}
public static BlobType fromValue(String type) {
return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(type,
"type")));
}
}

View File

@ -18,17 +18,17 @@
*/
package org.jclouds.azure.storage.blob.domain;
import java.util.SortedSet;
import java.util.Set;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.BoundedSet;
/**
*
* @author Adrian Cole
*/
public interface ListBlobsResponse extends BoundedSortedSet<ListableBlobProperties> {
public interface ListBlobsResponse extends BoundedSet<BlobProperties> {
String getDelimiter();
SortedSet<String> getBlobPrefixes();
Set<String> getBlobPrefixes();
}

View File

@ -1,60 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.domain;
import java.net.URI;
import java.util.Date;
/**
*
* @author Adrian Cole
*
*/
public interface ListableBlobProperties extends Comparable<ListableBlobProperties> {
URI getUrl();
String getName();
Date getLastModified();
String getETag();
Long getSize();
/**
*
* A standard MIME type describing the format of the contents. If none is provided, the default
* is binary/octet-stream.
*
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17"/>
*/
String getContentType();
/**
* Specifies what content encodings have been applied to the object and thus what decoding
* mechanisms must be applied in order to obtain the media-type referenced by the Content-Type
* header field.
*
* @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.11" />
*/
public String getContentEncoding();
public String getContentLanguage();
}

View File

@ -34,52 +34,52 @@ import com.google.inject.ImplementedBy;
@ImplementedBy(MutableBlobPropertiesImpl.class)
public interface MutableBlobProperties extends BlobProperties {
/**
* @see ListableContainerProperties#setUrl
* @see ListableContainerProperties#getUrl
*/
void setUrl(URI url);
/**
* @see ListableContainerProperties#setName
* @see ListableContainerProperties#getName
*/
void setName(String name);
/**
* @see ListableContainerProperties#setLastModified
* @see ListableContainerProperties#getLastModified
*/
void setLastModified(Date lastModified);
/**
* @see ListableContainerProperties#setETag
* @see ListableContainerProperties#getETag
*/
void setETag(String eTag);
/**
* @see ListableContainerProperties#setSize
* @see ListableContainerProperties#getContentLength
*/
void setSize(long size);
void setContentLength(long size);
/**
* @see ListableContainerProperties#setContentMD5
* @see ListableContainerProperties#getContentMD5
*/
void setContentMD5(byte[] md5);
/**
* @see ListableContainerProperties#setContentType
* @see ListableContainerProperties#getContentType
*/
void setContentType(String contentType);
/**
* @see ListableContainerProperties#setContentEncoding
* @see ListableContainerProperties#getContentEncoding
*/
void setContentEncoding(String contentEncoding);
/**
* @see ListableContainerProperties#setContentLanguage
* @see ListableContainerProperties#getContentLanguage
*/
void setContentLanguage(String contentLanguage);
/**
* @see ListableContainerProperties#setMetadata
* @see ListableContainerProperties#getMetadata
*/
void setMetadata(Map<String, String> metadata);

View File

@ -22,10 +22,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.net.URI;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import org.jclouds.azure.storage.blob.domain.ListableBlobProperties;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.BlobType;
import com.google.common.collect.Maps;
import com.google.inject.internal.Nullable;
/**
@ -33,31 +37,53 @@ import com.google.inject.internal.Nullable;
*
* @author Adrian Cole
*/
public class ListableBlobPropertiesImpl implements Serializable, ListableBlobProperties {
public class BlobPropertiesImpl implements Serializable, BlobProperties {
/** The serialVersionUID */
private static final long serialVersionUID = -4648755473986695062L;
private final BlobType type;
private final String name;
private final URI url;
private final Date lastModified;
private final String eTag;
private final long size;
private final String contentType;
private final byte[] contentMD5;
private final String contentEncoding;
private final String contentLanguage;
private final Map<String, String> metadata = Maps.newHashMap();
public ListableBlobPropertiesImpl(String name, URI url, Date lastModified, String eTag,
long size, String contentType, @Nullable String contentEncoding,
@Nullable String contentLanguage) {
public BlobPropertiesImpl(BlobType type, String name, URI url, Date lastModified, String eTag,
long size, String contentType, @Nullable byte[] contentMD5,
@Nullable String contentEncoding, @Nullable String contentLanguage,
Map<String, String> metadata) {
this.type = checkNotNull(type, "type");
this.name = checkNotNull(name, "name");
this.url = checkNotNull(url, "url");
this.lastModified = checkNotNull(lastModified, "lastModified");
this.eTag = checkNotNull(eTag, "eTag");
this.size = size;
this.contentType = checkNotNull(contentType, "contentType");
this.contentMD5 = contentMD5;
this.contentEncoding = contentEncoding;
this.contentLanguage = contentLanguage;
this.metadata.putAll(checkNotNull(metadata, "metadata"));
}
/**
*{@inheritDoc}
*/
@Override
public byte[] getContentMD5() {
return contentMD5;
}
/**
*{@inheritDoc}
*/
@Override
public BlobType getType() {
return type;
}
/**
@ -98,14 +124,14 @@ public class ListableBlobPropertiesImpl implements Serializable, ListableBlobPro
/**
*{@inheritDoc}
*/
public Long getSize() {
public Long getContentLength() {
return size;
}
/**
*{@inheritDoc}
*/
public int compareTo(ListableBlobProperties o) {
public int compareTo(BlobProperties o) {
return (this == o) ? 0 : getName().compareTo(o.getName());
}
@ -123,11 +149,14 @@ public class ListableBlobPropertiesImpl implements Serializable, ListableBlobPro
int result = 1;
result = prime * result + ((contentEncoding == null) ? 0 : contentEncoding.hashCode());
result = prime * result + ((contentLanguage == null) ? 0 : contentLanguage.hashCode());
result = prime * result + Arrays.hashCode(contentMD5);
result = prime * result + ((contentType == null) ? 0 : contentType.hashCode());
result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + (int) (size ^ (size >>> 32));
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((url == null) ? 0 : url.hashCode());
return result;
}
@ -140,7 +169,7 @@ public class ListableBlobPropertiesImpl implements Serializable, ListableBlobPro
return false;
if (getClass() != obj.getClass())
return false;
ListableBlobPropertiesImpl other = (ListableBlobPropertiesImpl) obj;
BlobPropertiesImpl other = (BlobPropertiesImpl) obj;
if (contentEncoding == null) {
if (other.contentEncoding != null)
return false;
@ -151,6 +180,8 @@ public class ListableBlobPropertiesImpl implements Serializable, ListableBlobPro
return false;
} else if (!contentLanguage.equals(other.contentLanguage))
return false;
if (!Arrays.equals(contentMD5, other.contentMD5))
return false;
if (contentType == null) {
if (other.contentType != null)
return false;
@ -166,6 +197,11 @@ public class ListableBlobPropertiesImpl implements Serializable, ListableBlobPro
return false;
} else if (!lastModified.equals(other.lastModified))
return false;
if (metadata == null) {
if (other.metadata != null)
return false;
} else if (!metadata.equals(other.metadata))
return false;
if (name == null) {
if (other.name != null)
return false;
@ -173,6 +209,11 @@ public class ListableBlobPropertiesImpl implements Serializable, ListableBlobPro
return false;
if (size != other.size)
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
if (url == null) {
if (other.url != null)
return false;
@ -181,4 +222,9 @@ public class ListableBlobPropertiesImpl implements Serializable, ListableBlobPro
return true;
}
@Override
public Map<String, String> getMetadata() {
return metadata;
}
}

View File

@ -19,38 +19,41 @@
package org.jclouds.azure.storage.blob.domain.internal;
import java.net.URI;
import java.util.SortedSet;
import java.util.Set;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableBlobProperties;
import org.jclouds.azure.storage.domain.internal.BoundedTreeSet;
import org.jclouds.azure.storage.domain.internal.BoundedHashSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
*
* @author Adrian Cole
*
*/
public class TreeSetListBlobsResponse extends BoundedTreeSet<ListableBlobProperties> implements
public class HashSetListBlobsResponse extends BoundedHashSet<BlobProperties> implements
ListBlobsResponse {
/** The serialVersionUID */
private static final long serialVersionUID = -4475709781001190244L;
public TreeSetListBlobsResponse(Iterable<ListableBlobProperties> contents, URI url, String prefix,
protected final String delimiter;
protected final Set<String> blobPrefixes = Sets.newHashSet();
public HashSetListBlobsResponse(Iterable<BlobProperties> contents, URI url, String prefix,
String marker, Integer maxResults, String nextMarker, String delimiter,
SortedSet<String> blobPrefixes) {
Iterable<String> blobPrefixes) {
super(contents, url, prefix, marker, maxResults, nextMarker);
this.delimiter = delimiter;
this.blobPrefixes = blobPrefixes;
Iterables.addAll(this.blobPrefixes, blobPrefixes);
}
protected final String delimiter;
protected final SortedSet<String> blobPrefixes;
public String getDelimiter() {
return delimiter;
}
public SortedSet<String> getBlobPrefixes() {
public Set<String> getBlobPrefixes() {
return blobPrefixes;
}
}

View File

@ -24,7 +24,8 @@ import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import org.jclouds.azure.storage.blob.domain.ListableBlobProperties;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.BlobType;
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
import com.google.common.collect.Maps;
@ -39,6 +40,7 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
/** The serialVersionUID */
private static final long serialVersionUID = -4648755473986695062L;
private BlobType type = BlobType.BLOCK_BLOB;
private String name;
private URI url;
private Date lastModified;
@ -53,6 +55,20 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
public MutableBlobPropertiesImpl() {
}
/**
*{@inheritDoc}
*/
public BlobType getType() {
return type;
}
/**
*{@inheritDoc}
*/
public void setType(BlobType type) {
this.type = type;
}
/**
*{@inheritDoc}
*/
@ -91,14 +107,14 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
/**
*{@inheritDoc}
*/
public Long getSize() {
public Long getContentLength() {
return size;
}
/**
*{@inheritDoc}
*/
public int compareTo(ListableBlobProperties o) {
public int compareTo(BlobProperties o) {
return (this == o) ? 0 : getName().compareTo(o.getName());
}
@ -171,7 +187,7 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
/**
*{@inheritDoc}
*/
public void setSize(long size) {
public void setContentLength(long size) {
this.size = size;
}
@ -211,6 +227,7 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + (int) (size ^ (size >>> 32));
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((url == null) ? 0 : url.hashCode());
return result;
}
@ -263,6 +280,11 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
return false;
if (size != other.size)
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
if (url == null) {
if (other.url != null)
return false;

View File

@ -77,9 +77,9 @@ public class ParseBlobFromHeadersAndHttpContent implements Function<HttpResponse
}
if (contentRange == null && contentLength != null) {
object.getProperties().setSize(object.getContentLength());
object.getProperties().setContentLength(object.getContentLength());
} else if (contentRange != null) {
object.getProperties().setSize(
object.getProperties().setContentLength(
Long.parseLong(contentRange.substring(contentRange.lastIndexOf('/') + 1)));
}
}

View File

@ -58,7 +58,7 @@ public class ParseBlobPropertiesFromHeaders implements
MutableBlobProperties to = blobToBlobProperties.apply(base);
if (from.getFirstHeaderOrNull("Content-Range") != null) {
String range = from.getFirstHeaderOrNull("Content-Range");
to.setSize(Long.parseLong(range.split("/")[1]));
to.setContentLength(Long.parseLong(range.split("/")[1]));
}
to.setContentLanguage(from.getFirstHeaderOrNull(HttpHeaders.CONTENT_LANGUAGE));
to.setContentEncoding(from.getFirstHeaderOrNull(HttpHeaders.CONTENT_ENCODING));

View File

@ -18,6 +18,8 @@
*/
package org.jclouds.azure.storage.blob.handlers;
import java.io.ByteArrayInputStream;
import javax.annotation.Resource;
import javax.inject.Named;
@ -72,7 +74,7 @@ public class AzureBlobClientErrorRetryHandler implements HttpRetryHandler {
} else if (response.getStatusCode() == 409) {
try {
AzureStorageError error = utils.parseAzureStorageErrorFromContent(command, response,
new String(content));
new ByteArrayInputStream(content));
if ("ContainerBeingDeleted".equals(error.getCode())) {
backoffHandler.imposeBackoffExponentialDelay(100L, 3, command.getFailureCount(),
command.toString());

View File

@ -26,8 +26,8 @@ import javax.inject.Inject;
import org.jclouds.azure.storage.blob.domain.ListableContainerProperties;
import org.jclouds.azure.storage.blob.domain.internal.ListableContainerPropertiesImpl;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.internal.BoundedTreeSet;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azure.storage.domain.internal.BoundedHashSet;
import org.jclouds.date.DateService;
import org.jclouds.http.functions.ParseSax;
@ -42,7 +42,7 @@ import com.google.common.collect.Sets;
* @author Adrian Cole
*/
public class AccountNameEnumerationResultsHandler extends
ParseSax.HandlerWithResult<BoundedSortedSet<ListableContainerProperties>> {
ParseSax.HandlerWithResult<BoundedSet<ListableContainerProperties>> {
private SortedSet<ListableContainerProperties> containerMetadata = Sets.newTreeSet();
private String prefix;
@ -62,8 +62,8 @@ public class AccountNameEnumerationResultsHandler extends
this.dateParser = dateParser;
}
public BoundedSortedSet<ListableContainerProperties> getResult() {
return new BoundedTreeSet<ListableContainerProperties>(containerMetadata, currentUrl, prefix,
public BoundedSet<ListableContainerProperties> getResult() {
return new BoundedHashSet<ListableContainerProperties>(containerMetadata, currentUrl, prefix,
marker, maxResults, nextMarker);
}
@ -87,7 +87,7 @@ public class AccountNameEnumerationResultsHandler extends
currentETag = null;
} else if (qName.equals("Url")) {
currentUrl = URI.create(currentText.toString().trim());
} else if (qName.equals("LastModified")) {
} else if (qName.equals("Last-Modified")) {
currentLastModified = dateParser.rfc822DateParse(currentText.toString().trim());
} else if (qName.equals("Etag")) {
currentETag = currentText.toString().trim();

View File

@ -20,20 +20,24 @@ package org.jclouds.azure.storage.blob.xml;
import java.net.URI;
import java.util.Date;
import java.util.SortedSet;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.BlobType;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableBlobProperties;
import org.jclouds.azure.storage.blob.domain.internal.ListableBlobPropertiesImpl;
import org.jclouds.azure.storage.blob.domain.internal.TreeSetListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.internal.BlobPropertiesImpl;
import org.jclouds.azure.storage.blob.domain.internal.HashSetListBlobsResponse;
import org.jclouds.date.DateService;
import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
@ -46,8 +50,7 @@ import com.google.common.collect.Sets;
*/
public class ContainerNameEnumerationResultsHandler extends
ParseSax.HandlerWithResult<ListBlobsResponse> {
private SortedSet<ListableBlobProperties> blobMetadata = Sets.newTreeSet();
private Set<BlobProperties> blobMetadata = Sets.newLinkedHashSet();
private String prefix;
private String marker;
private int maxResults;
@ -59,6 +62,7 @@ public class ContainerNameEnumerationResultsHandler extends
private StringBuilder currentText = new StringBuilder();
private final EncryptionService encryptionService;
private final DateService dateParser;
private String delimiter;
private String currentName;
@ -66,17 +70,23 @@ public class ContainerNameEnumerationResultsHandler extends
private String currentContentType;
private String currentContentEncoding;
private String currentContentLanguage;
private BlobType currentBlobType;
private boolean inBlob;
private boolean inBlobPrefix;
private SortedSet<String> blobPrefixes = Sets.newTreeSet();
private boolean inBlobMetadata;
private Set<String> blobPrefixes = Sets.newHashSet();
private byte[] currentContentMD5;
private Map<String, String> currentMetadata = Maps.newHashMap();
@Inject
public ContainerNameEnumerationResultsHandler(DateService dateParser) {
public ContainerNameEnumerationResultsHandler(EncryptionService encryptionService,
DateService dateParser) {
this.encryptionService = encryptionService;
this.dateParser = dateParser;
}
public ListBlobsResponse getResult() {
return new TreeSetListBlobsResponse(blobMetadata, containerUrl, prefix, marker, maxResults,
return new HashSetListBlobsResponse(blobMetadata, containerUrl, prefix, marker, maxResults,
nextMarker, delimiter, blobPrefixes);
}
@ -89,14 +99,22 @@ public class ContainerNameEnumerationResultsHandler extends
} else if (qName.equals("BlobPrefix")) {
inBlob = false;
inBlobPrefix = true;
} else if (qName.equals("Metadata")) {
inBlob = true;
inBlobMetadata = true;
} else if (qName.equals("EnumerationResults")) {
containerUrl = URI.create(attributes.getValue("ContainerName").toString().trim());
}
}
public void endElement(String uri, String name, String qName) {
if (inBlobMetadata && !qName.equals("Metadata")) {
currentMetadata.put(qName, currentText.toString().trim());
}
if (qName.equals("MaxResults")) {
maxResults = Integer.parseInt(currentText.toString().trim());
} else if (qName.equals("Metadata")) {
inBlobMetadata = false;
} else if (qName.equals("Marker")) {
marker = currentText.toString().trim();
marker = (marker.equals("")) ? null : marker;
@ -109,11 +127,15 @@ public class ContainerNameEnumerationResultsHandler extends
} else if (qName.equals("NextMarker")) {
nextMarker = currentText.toString().trim();
nextMarker = (nextMarker.equals("")) ? null : nextMarker;
} else if (qName.equals("BlobType")) {
currentBlobType = BlobType.fromValue(currentText.toString().trim());
} else if (qName.equals("Blob")) {
ListableBlobProperties md = new ListableBlobPropertiesImpl(currentName, currentUrl,
BlobProperties md = new BlobPropertiesImpl(currentBlobType, currentName, currentUrl,
currentLastModified, currentETag, currentSize, currentContentType,
currentContentEncoding, currentContentLanguage);
currentContentMD5, currentContentEncoding, currentContentLanguage,
currentMetadata);
blobMetadata.add(md);
currentBlobType = null;
currentName = null;
currentUrl = null;
currentLastModified = null;
@ -122,9 +144,11 @@ public class ContainerNameEnumerationResultsHandler extends
currentContentType = null;
currentContentEncoding = null;
currentContentLanguage = null;
currentContentMD5 = null;
currentMetadata = Maps.newHashMap();
} else if (qName.equals("Url")) {
currentUrl = HttpUtils.createUri(currentText.toString().trim());
} else if (qName.equals("LastModified")) {
} else if (qName.equals("Last-Modified")) {
currentLastModified = dateParser.rfc822DateParse(currentText.toString().trim());
} else if (qName.equals("Etag")) {
currentETag = currentText.toString().trim();
@ -133,15 +157,17 @@ public class ContainerNameEnumerationResultsHandler extends
currentName = currentText.toString().trim();
else if (inBlobPrefix)
blobPrefixes.add(currentText.toString().trim());
} else if (qName.equals("Size")) {
} else if (qName.equals("Content-Length")) {
currentSize = Long.parseLong(currentText.toString().trim());
} else if (qName.equals("ContentType")) {
} else if (qName.equals("Content-MD5")) {
currentContentMD5 = encryptionService.fromBase64String(currentText.toString().trim());
} else if (qName.equals("Content-Type")) {
currentContentType = currentText.toString().trim();
} else if (qName.equals("ContentEncoding")) {
} else if (qName.equals("Content-Encoding")) {
currentContentEncoding = currentText.toString().trim();
if (currentContentEncoding.equals(""))
currentContentEncoding = null;
} else if (qName.equals("ContentLanguage")) {
} else if (qName.equals("Content-Language")) {
currentContentLanguage = currentText.toString().trim();
if (currentContentLanguage.equals(""))
currentContentLanguage = null;

View File

@ -19,14 +19,14 @@
package org.jclouds.azure.storage.domain;
import java.net.URI;
import java.util.SortedSet;
import java.util.Set;
/**
*
* @author Adrian Cole
*
*/
public interface BoundedSortedSet<T> extends SortedSet<T> {
public interface BoundedSet<T> extends Set<T> {
URI getUrl();
String getPrefix();

View File

@ -19,9 +19,9 @@
package org.jclouds.azure.storage.domain.internal;
import java.net.URI;
import java.util.TreeSet;
import java.util.HashSet;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.BoundedSet;
import com.google.common.collect.Iterables;
@ -30,7 +30,7 @@ import com.google.common.collect.Iterables;
* @author Adrian Cole
*
*/
public class BoundedTreeSet<T> extends TreeSet<T> implements BoundedSortedSet<T> {
public class BoundedHashSet<T> extends HashSet<T> implements BoundedSet<T> {
/** The serialVersionUID */
private static final long serialVersionUID = -7133632087734650835L;
@ -40,7 +40,7 @@ public class BoundedTreeSet<T> extends TreeSet<T> implements BoundedSortedSet<T>
protected final Integer maxResults;
protected final String nextMarker;
public BoundedTreeSet(Iterable<T> contents, URI url, String prefix, String marker,
public BoundedHashSet(Iterable<T> contents, URI url, String prefix, String marker,
Integer maxResults, String nextMarker) {
Iterables.addAll(this, contents);
this.url = url;

View File

@ -54,7 +54,7 @@ import com.google.common.annotations.VisibleForTesting;
*
*/
@Singleton
public class SharedKeyAuthentication implements HttpRequestFilter {
public class SharedKeyLiteAuthentication implements HttpRequestFilter {
private final String[] firstHeadersToSign = new String[] { "Content-MD5",
HttpHeaders.CONTENT_TYPE, HttpHeaders.DATE };
@ -68,7 +68,7 @@ public class SharedKeyAuthentication implements HttpRequestFilter {
Logger signatureLog = Logger.NULL;
@Inject
public SharedKeyAuthentication(SignatureWire signatureWire,
public SharedKeyLiteAuthentication(SignatureWire signatureWire,
@Named(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT) String account,
@Named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY) String encodedKey,
@TimeStamp Provider<String> timeStampProvider, EncryptionService encryptionService) {
@ -105,7 +105,7 @@ public class SharedKeyAuthentication implements HttpRequestFilter {
if (signatureWire.enabled())
signatureWire.input(Utils.toInputStream(signature));
request.getHeaders().replaceValues(HttpHeaders.AUTHORIZATION,
Collections.singletonList("SharedKey " + account + ":" + signature));
Collections.singletonList("SharedKeyLite " + account + ":" + signature));
}
public String signString(String toSign) {

View File

@ -18,6 +18,8 @@
*/
package org.jclouds.azure.storage.handlers;
import java.io.ByteArrayInputStream;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -30,9 +32,10 @@ import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import com.google.common.base.Throwables;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables;
/**
* This will parse and set an appropriate exception on the command object.
@ -53,15 +56,16 @@ public class ParseAzureStorageErrorFromXmlContent implements HttpErrorHandler {
}
public void handleError(HttpCommand command, HttpResponse response) {
String content;
byte[] content;
try {
content = response.getContent() != null ? Utils.toStringAndClose(response.getContent())
content = response.getContent() != null ? ByteStreams.toByteArray(response.getContent())
: null;
if (content != null) {
String message = new String(content);
try {
if (content.indexOf('<') >= 0) {
if (message.indexOf('<') >= 0) {
AzureStorageError error = utils.parseAzureStorageErrorFromContent(command,
response, content);
response, new ByteArrayInputStream(content));
AzureStorageResponseException ex = new AzureStorageResponseException(command,
response, error);
if (error.getCode().equals("ContainerNotFound")) {
@ -70,10 +74,10 @@ public class ParseAzureStorageErrorFromXmlContent implements HttpErrorHandler {
command.setException(ex);
}
} else {
command.setException(new HttpResponseException(command, response, content));
command.setException(new HttpResponseException(command, response, message));
}
} catch (Exception he) {
command.setException(new HttpResponseException(command, response, content));
command.setException(new HttpResponseException(command, response, message));
Throwables.propagateIfPossible(he);
}
} else {
@ -82,7 +86,8 @@ public class ParseAzureStorageErrorFromXmlContent implements HttpErrorHandler {
} catch (Exception e) {
command.setException(new HttpResponseException(command, response));
Throwables.propagateIfPossible(e);
} finally {
Closeables.closeQuietly(response.getContent());
}
}
}

View File

@ -22,18 +22,22 @@ import java.util.concurrent.ExecutionException;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import org.jclouds.azure.storage.AzureQueue;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
import org.jclouds.azure.storage.options.CreateOptions;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.queue.binders.BindToXmlStringPayload;
import org.jclouds.azure.storage.queue.domain.QueueMetadata;
import org.jclouds.azure.storage.queue.options.PutMessageOptions;
import org.jclouds.azure.storage.queue.xml.AccountNameEnumerationResultsHandler;
import org.jclouds.azure.storage.reference.AzureStorageHeaders;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.QueryParams;
@ -64,8 +68,8 @@ import com.google.common.util.concurrent.ListenableFuture;
* @author Adrian Cole
*/
@SkipEncoding('/')
@RequestFilters(SharedKeyAuthentication.class)
@Headers(keys = AzureStorageHeaders.VERSION, values = "2009-07-17")
@RequestFilters(SharedKeyLiteAuthentication.class)
@Headers(keys = AzureStorageHeaders.VERSION, values = "2009-09-19")
@Endpoint(AzureQueue.class)
public interface AzureQueueAsyncClient {
@ -76,15 +80,13 @@ public interface AzureQueueAsyncClient {
@XMLResponseParser(AccountNameEnumerationResultsHandler.class)
@Path("/")
@QueryParams(keys = "comp", values = "list")
ListenableFuture<? extends BoundedSortedSet<QueueMetadata>> listQueues(
ListOptions... listOptions);
ListenableFuture<? extends BoundedSet<QueueMetadata>> listQueues(ListOptions... listOptions);
/**
* @see AzureQueueClient#createQueue
*/
@PUT
@Path("{queue}")
@QueryParams(keys = "restype", values = "queue")
ListenableFuture<Boolean> createQueue(@PathParam("queue") String queue, CreateOptions... options);
/**
@ -92,7 +94,20 @@ public interface AzureQueueAsyncClient {
*/
@DELETE
@Path("{queue}")
@QueryParams(keys = "restype", values = "queue")
ListenableFuture<Boolean> deleteQueue(@PathParam("queue") String queue);
ListenableFuture<Void> deleteQueue(@PathParam("queue") String queue);
/**
* @see AzureQueueClient#putMessage
*/
@POST
@Path("{queue}/messages")
ListenableFuture<Void> putMessage(@PathParam("queue") String queue,
@BinderParam(BindToXmlStringPayload.class) String message, PutMessageOptions... options);
/**
* @see AzureQueueClient#clearMessages
*/
@DELETE
@Path("{queue}/messages")
ListenableFuture<Void> clearMessages(@PathParam("queue") String queue);
}

View File

@ -21,12 +21,11 @@ package org.jclouds.azure.storage.queue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.PathParam;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azure.storage.options.CreateOptions;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.queue.domain.QueueMetadata;
import org.jclouds.azure.storage.queue.options.PutMessageOptions;
import org.jclouds.concurrent.Timeout;
import com.google.common.util.concurrent.ListenableFuture;
@ -64,7 +63,7 @@ public interface AzureQueueClient {
* controls the number or type of results requested
* @see ListOptions
*/
BoundedSortedSet<QueueMetadata> listQueues(ListOptions... listOptions);
BoundedSet<QueueMetadata> listQueues(ListOptions... listOptions);
/**
* The Create Queue operation creates a new queue under the specified account.
@ -83,7 +82,7 @@ public interface AzureQueueClient {
* @see CreateQueueOptions
*
*/
boolean createQueue(@PathParam("queue") String queue, CreateOptions... options);
boolean createQueue(String queue, CreateOptions... options);
/**
* The Delete Queue operation permanently deletes the specified queue.
@ -94,6 +93,34 @@ public interface AzureQueueClient {
* collection.
*
*/
boolean deleteQueue(@PathParam("queue") String queue);
void deleteQueue(String queue);
/**
* The Put Message operation adds a new message to the back of the message queue. A message may
* be up to 8 KB in size and must be in a format that can be included in an XML request with
* UTF-8 encoding.
*
* <p/>
*
* The message time-to-live specifies how long a message will remain in the queue, from the time
* it is added to the time it is retrieved and deleted. If a message is not retrieved before the
* time-to-live interval expires, the message is removed from the queue.
*
* If the message is too large, the service returns status code 400 (Bad Request).
*
*/
void putMessage(String queue, String message, PutMessageOptions... options);
/**
* The Clear Messages operation deletes all messages from the specified queue.
*
* <p/>
* If a queue contains a large number of messages, Clear Messages may time out before all
* messages have been deleted. In this case the Queue service will return status code 500
* (Internal Server Error), with the additional error code OperationTimedOut. If the operation
* times out, the client should continue to retry Clear Messages until it succeeds, to ensure
* that all messages have been deleted.
*/
@Timeout(duration = 10, timeUnit = TimeUnit.MINUTES)
void clearMessages(String queue);
}

View File

@ -41,20 +41,26 @@ import com.google.inject.Module;
*/
public class AzureQueueContextFactory {
public static RestContext<AzureQueueAsyncClient, AzureQueueClient> createContext(Properties properties,
Module... modules) {
public static RestContext<AzureQueueAsyncClient, AzureQueueClient> createContext(
Properties properties, Module... modules) {
return new AzureQueueContextBuilder(new AzureQueuePropertiesBuilder(properties).build())
.withModules(modules).buildContext();
}
public static RestContext<AzureQueueAsyncClient, AzureQueueClient> createContext(String account, String encodedKey,
Module... modules) {
public static RestContext<AzureQueueAsyncClient, AzureQueueClient> createContext(
Properties properties, String account, String encodedKey, Module... modules) {
return new AzureQueueContextBuilder(new AzureQueuePropertiesBuilder(properties)
.withCredentials(account, encodedKey).build()).withModules(modules).buildContext();
}
public static RestContext<AzureQueueAsyncClient, AzureQueueClient> createContext(String account,
String encodedKey, Module... modules) {
return new AzureQueueContextBuilder(new AzureQueuePropertiesBuilder(account, encodedKey)
.build()).withModules(modules).buildContext();
}
public static RestContext<AzureQueueAsyncClient, AzureQueueClient> createContext(URI endpoint, String account,
String encodedKey, Module... modules) {
public static RestContext<AzureQueueAsyncClient, AzureQueueClient> createContext(URI endpoint,
String account, String encodedKey, Module... modules) {
return new AzureQueueContextBuilder(new AzureQueuePropertiesBuilder(account, encodedKey)
.withEndpoint(endpoint).build()).withModules(modules).buildContext();
}

View File

@ -0,0 +1,37 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.queue.binders;
import javax.inject.Singleton;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.binders.BindToStringPayload;
/**
* Adds an payload to a request.
*
* @author Adrian Cole
*/
@Singleton
public class BindToXmlStringPayload extends BindToStringPayload {
public void bindToRequest(HttpRequest request, Object payload) {
super.bindToRequest(request, new StringBuilder().append("<QueueMessage><MessageText>")
.append(payload).append("</MessageText></QueueMessage>").toString());
}
}

View File

@ -0,0 +1,63 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.queue.options;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Contains options supported in the REST API for the Create Container operation. <h2>
* Usage</h2> The recommended way to instantiate a PutMessageOptions object is to statically
* import PutMessageOptions.* and invoke a static creation method followed by an instance
* mutator (if needed):
* <p/>
* <code>
* import static org.jclouds.azure.storage.queue.options.PutMessageOptions.Builder.*
* import org.jclouds.azure.storage.queue.AzureQueueClient;
* <p/>
* AzureQueueClient connection = // get connection
* connection.putMessage("containerName", withTTL());
* <code> *
*
* @see <a href="http://msdn.microsoft.com/en-us/library/dd179466.aspx" />
* @author Adrian Cole
*/
public class PutMessageOptions extends BaseHttpRequestOptions {
public static final PutMessageOptions NONE = new PutMessageOptions();
/**
* Specifies the time-to-live interval for the message, in seconds. The maximum time-to-live
* allowed is 7 days. If this parameter is omitted, the default time-to-live is 7 days.
*/
public PutMessageOptions withTTL(int seconds) {
this.queryParameters.put("messagettl", seconds + "");
return this;
}
public static class Builder {
/**
* @see PutMessageOptions#withTTL
*/
public static PutMessageOptions withTTL(int seconds) {
PutMessageOptions options = new PutMessageOptions();
return options.withTTL(seconds);
}
}
}

View File

@ -19,16 +19,17 @@
package org.jclouds.azure.storage.queue.xml;
import java.net.URI;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Set;
import javax.inject.Inject;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.internal.BoundedTreeSet;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azure.storage.domain.internal.BoundedHashSet;
import org.jclouds.azure.storage.queue.domain.QueueMetadata;
import org.jclouds.http.functions.ParseSax;
import com.google.common.collect.Sets;
/**
* Parses the following XML document:
* <p/>
@ -38,9 +39,9 @@ import org.jclouds.http.functions.ParseSax;
* @author Adrian Cole
*/
public class AccountNameEnumerationResultsHandler extends
ParseSax.HandlerWithResult<BoundedSortedSet<QueueMetadata>> {
ParseSax.HandlerWithResult<BoundedSet<QueueMetadata>> {
private SortedSet<QueueMetadata> metadata = new TreeSet<QueueMetadata>();
private Set<QueueMetadata> metadata = Sets.newLinkedHashSet();
private URI currentUrl;
private String prefix;
private String marker;
@ -54,8 +55,8 @@ public class AccountNameEnumerationResultsHandler extends
public AccountNameEnumerationResultsHandler() {
}
public BoundedSortedSet<QueueMetadata> getResult() {
return new BoundedTreeSet<QueueMetadata>(metadata, currentUrl, prefix, marker, maxResults,
public BoundedSet<QueueMetadata> getResult() {
return new BoundedHashSet<QueueMetadata>(metadata, currentUrl, prefix, marker, maxResults,
nextMarker);
}

View File

@ -18,14 +18,13 @@
*/
package org.jclouds.azure.storage.util;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import javax.inject.Inject;
import javax.inject.Provider;
import org.jclouds.azure.storage.domain.AzureStorageError;
import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
import org.jclouds.azure.storage.reference.AzureStorageHeaders;
import org.jclouds.azure.storage.xml.ErrorHandler;
import org.jclouds.http.HttpCommand;
@ -42,8 +41,8 @@ import org.jclouds.http.functions.ParseSax;
public class AzureStorageUtils {
@Inject
SharedKeyAuthentication signer;
SharedKeyLiteAuthentication signer;
@Inject
ParseSax.Factory factory;
@ -52,21 +51,13 @@ public class AzureStorageUtils {
public AzureStorageError parseAzureStorageErrorFromContent(HttpCommand command,
HttpResponse response, InputStream content) throws HttpException {
AzureStorageError error = (AzureStorageError) factory.create(errorHandlerProvider.get())
.parse(content);
AzureStorageError error = factory.create(errorHandlerProvider.get()).parse(content);
error.setRequestId(response.getFirstHeaderOrNull(AzureStorageHeaders.REQUEST_ID));
if ("AuthenticationFailed".equals(error.getCode())) {
error.setStringSigned(signer.createStringToSign(command.getRequest()));
error.setSignature(signer.signString(error.getStringSigned()));
}
return error;
}
public AzureStorageError parseAzureStorageErrorFromContent(HttpCommand command,
HttpResponse response, String content) throws HttpException {
return parseAzureStorageErrorFromContent(command, response, new ByteArrayInputStream(content
.getBytes()));
}
}

View File

@ -69,12 +69,12 @@ import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code AzureBlobClient}
* Tests behavior of {@code AzureBlobAsyncClient}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "azureblob.AzureBlobClientTest")
public class AzureBlobClientTest {
@Test(groups = "unit", testName = "azureblob.AzureBlobAsyncClientTest")
public class AzureBlobAsyncClientTest {
public void testListContainers() throws SecurityException, NoSuchMethodException {
Method method = AzureBlobAsyncClient.class.getMethod("listContainers", Array.newInstance(
@ -88,7 +88,7 @@ public class AzureBlobClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor
@ -111,7 +111,7 @@ public class AzureBlobClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor
@ -131,7 +131,7 @@ public class AzureBlobClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 2);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(httpMethod.getHeaders().get("Content-Length"), Collections.singletonList("0"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class);
@ -152,7 +152,7 @@ public class AzureBlobClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.DELETE);
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnVoidIf2xx.class);
// TODO check generic type of response parser
@ -174,7 +174,7 @@ public class AzureBlobClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 4);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(httpMethod.getHeaders().get("x-ms-meta-foo"), Collections.singletonList("bar"));
assertEquals(httpMethod.getHeaders().get("x-ms-prop-publicaccess"), Collections
.singletonList("true"));
@ -199,7 +199,7 @@ public class AzureBlobClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 2);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(httpMethod.getHeaders().get("Content-Length"), Collections.singletonList("0"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class);
@ -220,9 +220,9 @@ public class AzureBlobClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.DELETE);
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class);
ReturnVoidIf2xx.class);
// TODO check generic type of response parser
assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
@ -241,7 +241,7 @@ public class AzureBlobClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 4);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(httpMethod.getHeaders().get("x-ms-meta-foo"), Collections.singletonList("bar"));
assertEquals(httpMethod.getHeaders().get("x-ms-prop-publicaccess"), Collections
.singletonList("true"));
@ -266,7 +266,7 @@ public class AzureBlobClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor
@ -286,7 +286,7 @@ public class AzureBlobClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor
@ -305,7 +305,7 @@ public class AzureBlobClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.HEAD);
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ParseContainerPropertiesFromHeaders.class);
assertEquals(processor
@ -327,7 +327,7 @@ public class AzureBlobClientTest {
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList("0"));
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(httpMethod.getHeaders().get("x-ms-meta-key"), Collections.singletonList("value"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
@ -348,7 +348,7 @@ public class AzureBlobClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 3);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(httpMethod.getHeaders().get(HttpHeaders.CONTENT_LENGTH), Collections
.singletonList("0"));
assertEquals(httpMethod.getHeaders().get("x-ms-meta-key"), Collections.singletonList("value"));

View File

@ -26,7 +26,7 @@ import java.lang.reflect.UndeclaredThrowableException;
import java.net.URI;
import java.net.URL;
import java.security.SecureRandom;
import java.util.SortedSet;
import java.util.Set;
import org.jclouds.azure.storage.AzureStorageResponseException;
import org.jclouds.azure.storage.blob.domain.AzureBlob;
@ -34,8 +34,9 @@ import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableContainerProperties;
import org.jclouds.azure.storage.blob.options.CreateContainerOptions;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.encryption.EncryptionService;
import org.jclouds.encryption.internal.JCEEncryptionService;
import org.jclouds.http.HttpResponseException;
@ -46,6 +47,7 @@ import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
import com.google.inject.internal.Iterables;
/**
* Tests behavior of {@code AzureBlobClient}
@ -70,8 +72,7 @@ public class AzureBlobClientLiveTest {
@Test
public void testListContainers() throws Exception {
SortedSet<ListableContainerProperties> response = connection.listContainers();
Set<ListableContainerProperties> response = connection.listContainers();
assert null != response;
long initialContainerCount = response.size();
assertTrue(initialContainerCount >= 0);
@ -97,7 +98,7 @@ public class AzureBlobClientLiveTest {
throw e;
}
}
SortedSet<ListableContainerProperties> response = connection.listContainers();
Set<ListableContainerProperties> response = connection.listContainers();
assert null != response;
long containerCount = response.size();
assertTrue(containerCount >= 1);
@ -132,9 +133,16 @@ public class AzureBlobClientLiveTest {
public void testCreatePublicRootContainer() throws Exception {
try {
connection.deleteRootContainer();
} catch (AzureStorageResponseException e) {
sleepIfWaitingForDeleteToFinish(e);
} catch (ContainerNotFoundException e) {
Thread.sleep(5000);
} catch (AzureStorageResponseException htpe) {
if (htpe.getResponse().getStatusCode() == 409) {// TODO look for specific message
Thread.sleep(5000);
} else {
throw htpe;
}
}
boolean created = false;
while (!created) {
try {
@ -153,18 +161,10 @@ public class AzureBlobClientLiveTest {
"https://%s.blob.core.windows.net/%%24root", account)));
}
private void sleepIfWaitingForDeleteToFinish(AzureStorageResponseException e)
throws InterruptedException {
if (e.getResponse().getStatusCode() == 409) {
Thread.sleep(5000);
}
}
@Test
public void testListContainersWithOptions() throws Exception {
BoundedSortedSet<ListableContainerProperties> response = connection
BoundedSet<ListableContainerProperties> response = connection
.listContainers(ListOptions.Builder.prefix(privateContainer).maxResults(1));
assert null != response;
long initialContainerCount = response.size();
@ -175,7 +175,7 @@ public class AzureBlobClientLiveTest {
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testCreatePublicRootContainer" })
public void testDeleteRootContainer() throws Exception {
assert connection.deleteRootContainer();
connection.deleteRootContainer();
// TODO loop for up to 30 seconds checking if they are really gone
}
@ -184,7 +184,7 @@ public class AzureBlobClientLiveTest {
public void testListOwnedContainers() throws Exception {
// Test default listing
SortedSet<ListableContainerProperties> response = connection.listContainers();
Set<ListableContainerProperties> response = connection.listContainers();
// assertEquals(response.size(), initialContainerCount + 2);// if the containers already
// exist, this will fail
@ -192,12 +192,12 @@ public class AzureBlobClientLiveTest {
response = connection.listContainers(ListOptions.Builder.prefix(
privateContainer.substring(0, privateContainer.length() - 1)).maxResults(1));
assertEquals(response.size(), 1);
assertEquals(response.first().getName(), privateContainer);
assertEquals(Iterables.getOnlyElement(response).getName(), privateContainer);
response = connection.listContainers(ListOptions.Builder.prefix(publicContainer)
.maxResults(1));
assertEquals(response.size(), 1);
assertEquals(response.first().getName(), publicContainer);
assertEquals(Iterables.getOnlyElement(response).getName(), publicContainer);
}

View File

@ -30,5 +30,4 @@ import org.testng.annotations.Test;
@Test(groups = { "integration", "live" }, testName = "azureblob.AzureBlobIntegrationTest")
public class AzureBlobIntegrationTest extends
BaseBlobIntegrationTest<AzureBlobAsyncClient, AzureBlobClient> {
}

View File

@ -42,8 +42,8 @@ import org.jclouds.azure.storage.blob.domain.ListableContainerProperties;
import org.jclouds.azure.storage.blob.domain.internal.ListableContainerPropertiesImpl;
import org.jclouds.azure.storage.blob.options.CreateContainerOptions;
import org.jclouds.azure.storage.blob.options.ListBlobsOptions;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.internal.BoundedTreeSet;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azure.storage.domain.internal.BoundedHashSet;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.attr.ConsistencyModels;
@ -112,7 +112,7 @@ public class StubAzureBlobAsyncClient implements AzureBlobAsyncClient {
return immediateFuture(null);
}
public ListenableFuture<Boolean> deleteRootContainer() {
public ListenableFuture<Void> deleteRootContainer() {
throw new UnsupportedOperationException();
}
@ -149,9 +149,9 @@ public class StubAzureBlobAsyncClient implements AzureBlobAsyncClient {
throw new UnsupportedOperationException();
}
public ListenableFuture<? extends BoundedSortedSet<ListableContainerProperties>> listContainers(
public ListenableFuture<? extends BoundedSet<ListableContainerProperties>> listContainers(
ListOptions... listOptions) {
return immediateFuture(new BoundedTreeSet<ListableContainerProperties>(Iterables.transform(
return immediateFuture(new BoundedHashSet<ListableContainerProperties>(Iterables.transform(
blobStore.getContainerToBlobs().keySet(),
new Function<String, ListableContainerProperties>() {
public ListableContainerProperties apply(String name) {

View File

@ -26,8 +26,8 @@ import java.util.SortedSet;
import org.jclouds.azure.storage.blob.domain.ListableContainerProperties;
import org.jclouds.azure.storage.blob.domain.internal.ListableContainerPropertiesImpl;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.internal.BoundedTreeSet;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azure.storage.domain.internal.BoundedHashSet;
import org.jclouds.date.DateService;
import org.jclouds.http.functions.BaseHandlerTest;
import org.testng.annotations.BeforeTest;
@ -65,11 +65,11 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
contents.add(new ListableContainerPropertiesImpl(URI
.create("http://myaccount.blob.core.windows.net/textfiles"), dateService
.rfc822DateParse("Wed, 15 Aug 2008 20:39:39 GMT"), "0x8CACB9BD7BACAC3"));
BoundedSortedSet<ListableContainerProperties> list = new BoundedTreeSet<ListableContainerProperties>(
BoundedSet<ListableContainerProperties> list = new BoundedHashSet<ListableContainerProperties>(
contents, URI.create("http://myaccount.blob.core.windows.net/"), null, null, 3,
"video");
BoundedSortedSet<ListableContainerProperties> result = (BoundedSortedSet<ListableContainerProperties>) factory
BoundedSet<ListableContainerProperties> result = (BoundedSet<ListableContainerProperties>) factory
.create(injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
assertEquals(result, list);
@ -87,10 +87,10 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
.create("http://myaccount.blob.core.windows.net/textfiles"), dateService
.rfc822DateParse("Wed, 15 Aug 2008 20:39:39 GMT"), "0x8CACB9BD7BACAC3"));
InputStream is = getClass().getResourceAsStream("/blob/test_list_containers_options.xml");
BoundedSortedSet<ListableContainerProperties> list = new BoundedTreeSet<ListableContainerProperties>(
BoundedSet<ListableContainerProperties> list = new BoundedHashSet<ListableContainerProperties>(
contents, URI.create("http://myaccount.blob.core.windows.net"), "prefix", "marker",
1, "video");
BoundedSortedSet<ListableContainerProperties> result = (BoundedSortedSet<ListableContainerProperties>) factory
BoundedSet<ListableContainerProperties> result = (BoundedSet<ListableContainerProperties>) factory
.create(injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
assertEquals(result, list);
}

View File

@ -22,17 +22,19 @@ import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.net.URI;
import java.util.SortedSet;
import java.util.Set;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.BlobType;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableBlobProperties;
import org.jclouds.azure.storage.blob.domain.internal.ListableBlobPropertiesImpl;
import org.jclouds.azure.storage.blob.domain.internal.TreeSetListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.internal.BlobPropertiesImpl;
import org.jclouds.azure.storage.blob.domain.internal.HashSetListBlobsResponse;
import org.jclouds.date.DateService;
import org.jclouds.http.functions.BaseHandlerTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
/**
@ -54,21 +56,22 @@ public class ContainerNameEnumerationResultsHandlerTest extends BaseHandlerTest
public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/blob/test_list_blobs.xml");
SortedSet<ListableBlobProperties> contents = Sets.newTreeSet();
contents.add(new ListableBlobPropertiesImpl("blob1.txt", URI
Set<BlobProperties> contents = Sets.newTreeSet();
contents.add(new BlobPropertiesImpl(BlobType.BLOCK_BLOB, "blob1.txt", URI
.create("http://myaccount.blob.core.windows.net/mycontainer/blob1.txt"), dateService
.rfc822DateParse("Thu, 18 Sep 2008 18:41:57 GMT"), "0x8CAE7D55D050B8B", 8,
"text/plain; charset=UTF-8", null, null));
contents.add(new ListableBlobPropertiesImpl("blob2.txt", URI
"text/plain; charset=UTF-8", null, null, null, ImmutableMap.<String, String> of()));
contents.add(new BlobPropertiesImpl(BlobType.BLOCK_BLOB, "blob2.txt", URI
.create("http://myaccount.blob.core.windows.net/mycontainer/blob2.txt"), dateService
.rfc822DateParse("Thu, 18 Sep 2008 18:41:57 GMT"), "0x8CAE7D55CF6C339", 14,
"text/plain; charset=UTF-8", null, null));
contents.add(new ListableBlobPropertiesImpl("newblob1.txt", URI
"text/plain; charset=UTF-8", null, null, null, ImmutableMap.<String, String> of()));
contents.add(new BlobPropertiesImpl(BlobType.PAGE_BLOB, "newblob1.txt", URI
.create("http://myaccount.blob.core.windows.net/mycontainer/newblob1.txt"),
dateService.rfc822DateParse("Thu, 18 Sep 2008 18:41:57 GMT"), "0x8CAE7D55CF6C339",
25, "text/plain; charset=UTF-8", null, null));
25, "text/plain; charset=UTF-8", null, null, null, ImmutableMap
.<String, String> of()));
ListBlobsResponse list = new TreeSetListBlobsResponse(contents, URI
ListBlobsResponse list = new HashSetListBlobsResponse(contents, URI
.create("http://myaccount.blob.core.windows.net/mycontainer"),
"myfolder/", null, 4, "newblob2.txt", "/", Sets.<String> newTreeSet());

View File

@ -1,110 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.filters;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Executors.sameThreadExecutor;
import static org.testng.Assert.assertTrue;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import org.jclouds.azure.storage.AzureBlob;
import org.jclouds.azure.storage.config.AzureStorageRestClientModule;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestClientFactory;
import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.config.RestModule;
import org.jclouds.util.Jsr330;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code JaxrsAnnotationProcessor}
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "azure.SharedKeyAuthenticationLiveTest")
public class SharedKeyAuthenticationLiveTest {
@RequestFilters(SharedKeyAuthentication.class)
@Endpoint(AzureBlob.class)
public interface IntegrationTestClient {
@GET
@Path("/")
@QueryParams(keys = "comp", values = "list")
ListenableFuture<String> authenticate();
}
private Injector injector;
private IntegrationTestClient client;
private String uri;
@Test
public void testAuthentication() throws Exception {
String response = client.authenticate().get(10, TimeUnit.SECONDS);
assertTrue(response.contains(uri), String.format("expected %s to contain %s", response, uri));
}
@BeforeClass
void setupFactory() {
final String account = checkNotNull(System.getProperty("jclouds.test.user"),
"jclouds.test.user");
final String key = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
uri = "http://" + account + ".blob.core.windows.net";
injector = Guice.createInjector(
new AbstractModule() {
@Override
protected void configure() {
bind(URI.class).annotatedWith(AzureBlob.class).toInstance(URI.create(uri));
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT))
.to(account);
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY))
.to(key);
bindConstant()
.annotatedWith(
Jsr330
.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_SESSIONINTERVAL))
.to(1l);
}
}, new AzureStorageRestClientModule(), new RestModule(), new Log4JLoggingModule(),
new ExecutorServiceModule(sameThreadExecutor()),
new JavaUrlHttpCommandExecutorServiceModule());
RestClientFactory factory = injector.getInstance(RestClientFactory.class);
client = factory.create(IntegrationTestClient.class);
}
}

View File

@ -42,13 +42,17 @@ import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
@Test(groups = "unit", testName = "azurestorage.SharedKeyAuthenticationTest")
public class SharedKeyAuthenticationTest {
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "azurestorage.SharedKeyLiteAuthenticationTest")
public class SharedKeyLiteAuthenticationTest {
private static final String KEY = Base64.encodeBytes("bar".getBytes());
private static final String ACCOUNT = "foo";
private Injector injector;
private SharedKeyAuthentication filter;
private SharedKeyLiteAuthentication filter;
@DataProvider(parallel = true)
public Object[][] dataProvider() {
@ -145,7 +149,7 @@ public class SharedKeyAuthenticationTest {
}
});
filter = injector.getInstance(SharedKeyAuthentication.class);
filter = injector.getInstance(SharedKeyLiteAuthentication.class);
}
}

View File

@ -18,51 +18,52 @@
*/
package org.jclouds.azure.storage.queue;
import static com.google.common.util.concurrent.Executors.sameThreadExecutor;
import static org.jclouds.azure.storage.options.CreateOptions.Builder.withMetadata;
import static org.jclouds.azure.storage.options.ListOptions.Builder.maxResults;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Collections;
import javax.inject.Singleton;
import javax.ws.rs.HttpMethod;
import org.jclouds.azure.storage.AzureQueue;
import org.jclouds.azure.storage.config.AzureStorageRestClientModule;
import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
import org.jclouds.azure.storage.options.CreateOptions;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.queue.options.PutMessageOptions;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.date.TimeStamp;
import org.jclouds.encryption.internal.Base64;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.ReturnVoidIf2xx;
import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.rest.config.RestModule;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.functions.ThrowResourceNotFoundOn404;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code AzureQueueClient}
* Tests behavior of {@code AzureQueueAsyncClient}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "cloudservers.AzureQueueClientTest")
public class AzureQueueClientTest {
@Test(groups = "unit", testName = "azurequeue.AzureQueueAsyncClientTest")
public class AzureQueueAsyncClientTest extends RestClientTest<AzureQueueAsyncClient> {
private static final Class<? extends ListOptions[]> listOptionsVarargsClass = new ListOptions[] {}
.getClass();
private static final Class<? extends CreateOptions[]> createOptionsVarargsClass = new CreateOptions[] {}
@ -79,7 +80,7 @@ public class AzureQueueClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor
@ -101,7 +102,7 @@ public class AzureQueueClientTest {
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor
@ -117,11 +118,11 @@ public class AzureQueueClientTest {
new Object[] { "queue" });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/queue");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=queue");
assertEquals(httpMethod.getEndpoint().getQuery(), null);
assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 2);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(httpMethod.getHeaders().get("Content-Length"), Collections.singletonList("0"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class);
@ -131,26 +132,6 @@ public class AzureQueueClientTest {
ThrowResourceNotFoundOn404.class);
}
public void testDeleteQueue() throws SecurityException, NoSuchMethodException {
Method method = AzureQueueAsyncClient.class.getMethod("deleteQueue", String.class);
GeneratedHttpRequest<AzureQueueAsyncClient> httpMethod = processor.createRequest(method,
new Object[] { "queue" });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/queue");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=queue");
assertEquals(httpMethod.getMethod(), HttpMethod.DELETE);
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnTrueIf2xx.class);
// TODO check generic type of response parser
assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ThrowResourceNotFoundOn404.class);
}
public void testCreateQueueOptions() throws SecurityException, NoSuchMethodException {
Method method = AzureQueueAsyncClient.class.getMethod("createQueue", String.class,
createOptionsVarargsClass);
@ -159,11 +140,11 @@ public class AzureQueueClientTest {
new Object[] { "queue", withMetadata(ImmutableMultimap.of("foo", "bar")) });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/queue");
assertEquals(httpMethod.getEndpoint().getQuery(), "restype=queue");
assertEquals(httpMethod.getEndpoint().getQuery(), null);
assertEquals(httpMethod.getMethod(), HttpMethod.PUT);
assertEquals(httpMethod.getHeaders().size(), 3);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
.singletonList("2009-09-19"));
assertEquals(httpMethod.getHeaders().get("x-ms-meta-foo"), Collections.singletonList("bar"));
assertEquals(httpMethod.getHeaders().get("Content-Length"), Collections.singletonList("0"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
@ -174,9 +155,96 @@ public class AzureQueueClientTest {
ThrowResourceNotFoundOn404.class);
}
@BeforeClass
void setupFactory() {
Injector injector = Guice.createInjector(new AbstractModule() {
public void testDeleteQueue() throws SecurityException, NoSuchMethodException {
Method method = AzureQueueAsyncClient.class.getMethod("deleteQueue", String.class);
GeneratedHttpRequest<AzureQueueAsyncClient> httpMethod = processor.createRequest(method,
new Object[] { "queue" });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/queue");
assertEquals(httpMethod.getEndpoint().getQuery(), null);
assertEquals(httpMethod.getMethod(), HttpMethod.DELETE);
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-09-19"));
assertEquals(processor.createResponseParser(method, httpMethod).getClass(),
ReturnVoidIf2xx.class);
// TODO check generic type of response parser
assertEquals(processor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method).getClass(),
ThrowResourceNotFoundOn404.class);
}
public void testPutMessage() throws SecurityException, NoSuchMethodException, IOException {
Method method = AzureQueueAsyncClient.class.getMethod("putMessage", String.class,
String.class, Array.newInstance(PutMessageOptions.class, 0).getClass());
GeneratedHttpRequest<AzureQueueAsyncClient> httpMethod = processor.createRequest(method,
"queue", "message");
assertRequestLineEquals(httpMethod, "POST http://localhost:8080/queue/messages HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 63\nContent-Type: application/unknown\nx-ms-version: 2009-09-19\n");
assertPayloadEquals(httpMethod,
"<QueueMessage><MessageText>message</MessageText></QueueMessage>");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testPutMessageOptions() throws SecurityException, NoSuchMethodException, IOException {
Method method = AzureQueueAsyncClient.class.getMethod("putMessage", String.class,
String.class, Array.newInstance(PutMessageOptions.class, 0).getClass());
GeneratedHttpRequest<AzureQueueAsyncClient> httpMethod = processor.createRequest(method,
"queue", "message", PutMessageOptions.Builder.withTTL(3));
assertRequestLineEquals(httpMethod,
"POST http://localhost:8080/queue/messages?messagettl=3 HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 63\nContent-Type: application/unknown\nx-ms-version: 2009-09-19\n");
assertPayloadEquals(httpMethod,
"<QueueMessage><MessageText>message</MessageText></QueueMessage>");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testClearMessages() throws SecurityException, NoSuchMethodException, IOException {
Method method = AzureQueueAsyncClient.class.getMethod("clearMessages", String.class);
GeneratedHttpRequest<AzureQueueAsyncClient> httpMethod = processor.createRequest(method,
"queue");
assertRequestLineEquals(httpMethod, "DELETE http://localhost:8080/queue/messages HTTP/1.1");
assertHeadersEqual(httpMethod, "x-ms-version: 2009-09-19\n");
assertPayloadEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
@Override
protected void checkFilters(GeneratedHttpRequest<AzureQueueAsyncClient> httpMethod) {
assertEquals(httpMethod.getFilters().size(), 1);
assertEquals(httpMethod.getFilters().get(0).getClass(), SharedKeyLiteAuthentication.class);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<AzureQueueAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<AzureQueueAsyncClient>>() {
};
}
@Override
protected Module createModule() {
return new AbstractModule() {
@Override
protected void configure() {
bind(URI.class).annotatedWith(AzureQueue.class).toInstance(
@ -195,12 +263,14 @@ public class AzureQueueClientTest {
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_SESSIONINTERVAL)).to(
1l);
}
}, new AzureStorageRestClientModule(), new RestModule(), new ExecutorServiceModule(
sameThreadExecutor()), new JavaUrlHttpCommandExecutorServiceModule());
processor = injector.getInstance(Key
.get(new TypeLiteral<RestAnnotationProcessor<AzureQueueAsyncClient>>() {
}));
}
RestAnnotationProcessor<AzureQueueAsyncClient> processor;
@SuppressWarnings("unused")
@Provides
@TimeStamp
@Singleton
String provideTS() {
return "timestamp";
}
};
}
}

View File

@ -23,10 +23,11 @@ import static org.testng.Assert.assertTrue;
import java.security.SecureRandom;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azure.storage.options.CreateOptions;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.queue.domain.QueueMetadata;
import org.jclouds.azure.storage.queue.options.PutMessageOptions;
import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.testng.annotations.BeforeGroups;
@ -61,7 +62,7 @@ public class AzureQueueClientLiveTest {
@Test
public void testListQueues() throws Exception {
BoundedSortedSet<QueueMetadata> response = connection.listQueues();
BoundedSet<QueueMetadata> response = connection.listQueues();
assert null != response;
long initialQueueCount = response.size();
assertTrue(initialQueueCount >= 0);
@ -86,17 +87,16 @@ public class AzureQueueClientLiveTest {
}
}
}
BoundedSortedSet<QueueMetadata> response = connection.listQueues();
BoundedSet<QueueMetadata> response = connection.listQueues();
assert null != response;
long queueCount = response.size();
assertTrue(queueCount >= 1);
// TODO ... check to see the queue actually exists
}
@Test
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testCreateQueue" })
public void testListQueuesWithOptions() throws Exception {
BoundedSortedSet<QueueMetadata> response = connection.listQueues(ListOptions.Builder.prefix(
BoundedSet<QueueMetadata> response = connection.listQueues(ListOptions.Builder.prefix(
privateQueue).maxResults(1));
assert null != response;
long initialQueueCount = response.size();
@ -104,10 +104,17 @@ public class AzureQueueClientLiveTest {
assertEquals(privateQueue, response.getPrefix());
assertEquals(1, response.getMaxResults());
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testCreateQueue" })
public void testPutMessage() throws Exception {
connection.putMessage(privateQueue,"holycow",PutMessageOptions.Builder.withTTL(4));
// TODO loop for up to 30 seconds checking if they are really gone
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testPutMessage" })
public void testDeleteQueue() throws Exception {
assert connection.deleteQueue(privateQueue);
connection.clearMessages(privateQueue);
connection.deleteQueue(privateQueue);
// TODO loop for up to 30 seconds checking if they are really gone
}

View File

@ -23,8 +23,8 @@ import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.net.URI;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.internal.BoundedTreeSet;
import org.jclouds.azure.storage.domain.BoundedSet;
import org.jclouds.azure.storage.domain.internal.BoundedHashSet;
import org.jclouds.azure.storage.queue.domain.QueueMetadata;
import org.jclouds.http.functions.BaseHandlerTest;
import org.testng.annotations.Test;
@ -41,24 +41,24 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/queue/test_list_queues.xml");
BoundedSortedSet<QueueMetadata> list = new BoundedTreeSet<QueueMetadata>(ImmutableSortedSet.of(
BoundedSet<QueueMetadata> list = new BoundedHashSet<QueueMetadata>(ImmutableSortedSet.of(
new QueueMetadata("q1", URI.create("http://myaccount.queue.core.windows.net/q1")),
new QueueMetadata("q2", URI.create("http://myaccount.queue.core.windows.net/q2")),
new QueueMetadata("q3", URI.create("http://myaccount.queue.core.windows.net/q3"))),
URI.create("http://myaccount.queue.core.windows.net"), "q", null, 3, "q4");
BoundedSortedSet<QueueMetadata> result = (BoundedSortedSet<QueueMetadata>) factory.create(
BoundedSet<QueueMetadata> result = (BoundedSet<QueueMetadata>) factory.create(
injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
assertEquals(result, list);
}
public void testApplyInputStreamWithOptions() {
InputStream is = getClass().getResourceAsStream("/queue/test_list_queues_options.xml");
BoundedSortedSet<QueueMetadata> list = new BoundedTreeSet<QueueMetadata>(ImmutableSortedSet.of(
BoundedSet<QueueMetadata> list = new BoundedHashSet<QueueMetadata>(ImmutableSortedSet.of(
new QueueMetadata("q4", URI.create("http://myaccount.queue.core.windows.net/q4")),
new QueueMetadata("q5", URI.create("http://myaccount.queue.core.windows.net/q5"))),
URI.create("http://myaccount.queue.core.windows.net"), "q", "q4", 3, null);
BoundedSortedSet<QueueMetadata> result = (BoundedSortedSet<QueueMetadata>) factory.create(
BoundedSet<QueueMetadata> result = (BoundedSet<QueueMetadata>) factory.create(
injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
assertEquals(result, list);

View File

@ -30,22 +30,24 @@
<Blob>
<Name>blob1.txt</Name>
<Url>http://myaccount.blob.core.windows.net/mycontainer/blob1.txt</Url>
<LastModified>Thu, 18 Sep 2008 18:41:57 GMT</LastModified>
<Last-Modified>Thu, 18 Sep 2008 18:41:57 GMT</Last-Modified>
<Etag>0x8CAE7D55D050B8B</Etag>
<Size>8</Size>
<ContentType>text/plain; charset=UTF-8</ContentType>
<ContentEncoding />
<ContentLanguage />
<Content-Length>8</Content-Length>
<Content-Type>text/plain; charset=UTF-8</Content-Type>
<BlobType>BlockBlob</BlobType>
<Content-Encoding />
<Content-Language />
</Blob>
<Blob>
<Name>blob2.txt</Name>
<Url>http://myaccount.blob.core.windows.net/mycontainer/blob2.txt</Url>
<LastModified>Thu, 18 Sep 2008 18:41:57 GMT</LastModified>
<Last-Modified>Thu, 18 Sep 2008 18:41:57 GMT</Last-Modified>
<Etag>0x8CAE7D55CF6C339</Etag>
<Size>14</Size>
<ContentType>text/plain; charset=UTF-8</ContentType>
<ContentEncoding />
<ContentLanguage />
<Content-Length>14</Content-Length>
<Content-Type>text/plain; charset=UTF-8</Content-Type>
<BlobType>BlockBlob</BlobType>
<Content-Encoding />
<Content-Language />
</Blob>
<BlobPrefix>
<Name>myfolder/</Name>
@ -53,12 +55,13 @@
<Blob>
<Name>newblob1.txt</Name>
<Url>http://myaccount.blob.core.windows.net/mycontainer/newblob1.txt</Url>
<LastModified>Thu, 18 Sep 2008 18:41:57 GMT</LastModified>
<Last-Modified>Thu, 18 Sep 2008 18:41:57 GMT</Last-Modified>
<Etag>0x8CAE7D55CF6C339</Etag>
<Size>25</Size>
<ContentType>text/plain; charset=UTF-8</ContentType>
<ContentEncoding />
<ContentLanguage />
<Content-Length>25</Content-Length>
<Content-Type>text/plain; charset=UTF-8</Content-Type>
<BlobType>PageBlob</BlobType>
<Content-Encoding />
<Content-Language />
</Blob>
</Blobs>
<NextMarker>newblob2.txt</NextMarker>

View File

@ -29,17 +29,17 @@
<Containers>
<Container>
<Url>http://myaccount.blob.core.windows.net/audio</Url>
<LastModified>Wed, 13 Aug 2008 20:39:39 GMT</LastModified>
<Last-Modified>Wed, 13 Aug 2008 20:39:39 GMT</Last-Modified>
<Etag>0x8CACB9BD7C6B1B2</Etag>
</Container>
<Container>
<Url>http://myaccount.blob.core.windows.net/images</Url>
<LastModified>Wed, 14 Aug 2008 20:39:39 GMT</LastModified>
<Last-Modified>Wed, 14 Aug 2008 20:39:39 GMT</Last-Modified>
<Etag>0x8CACB9BD7C1EEEC</Etag>
</Container>
<Container>
<Url>http://myaccount.blob.core.windows.net/textfiles</Url>
<LastModified>Wed, 15 Aug 2008 20:39:39 GMT</LastModified>
<Last-Modified>Wed, 15 Aug 2008 20:39:39 GMT</Last-Modified>
<Etag>0x8CACB9BD7BACAC3</Etag>
</Container>
</Containers>

View File

@ -31,17 +31,17 @@
<Containers>
<Container>
<Url>http://myaccount.blob.core.windows.net/audio</Url>
<LastModified>Wed, 13 Aug 2008 20:39:39 GMT</LastModified>
<Last-Modified>Wed, 13 Aug 2008 20:39:39 GMT</Last-Modified>
<Etag>0x8CACB9BD7C6B1B2</Etag>
</Container>
<Container>
<Url>http://myaccount.blob.core.windows.net/images</Url>
<LastModified>Wed, 14 Aug 2008 20:39:39 GMT</LastModified>
<Last-Modified>Wed, 14 Aug 2008 20:39:39 GMT</Last-Modified>
<Etag>0x8CACB9BD7C1EEEC</Etag>
</Container>
<Container>
<Url>http://myaccount.blob.core.windows.net/textfiles</Url>
<LastModified>Wed, 15 Aug 2008 20:39:39 GMT</LastModified>
<Last-Modified>Wed, 15 Aug 2008 20:39:39 GMT</Last-Modified>
<Etag>0x8CACB9BD7BACAC3</Etag>
</Container>
</Containers>

View File

@ -1,32 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
<!--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
Copyright (C) 2009 Cloud Conscious, LLC.
<info@cloudconscious.com>
====================================================================
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
====================================================================
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
====================================================================
-->
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.
====================================================================
-->
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!--
For more configuration infromation and examples see the Apache Log4j
website: http://logging.apache.org/log4j/
-->
<!--
For more configuration infromation and examples see the Apache
Log4j website: http://logging.apache.org/log4j/
-->
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
debug="false">
<!-- A time/date based rolling appender -->
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
@ -43,68 +42,68 @@
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category] (Thread:NDC) Message\n
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
%m%n"/>
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds.log" />
<param name="Append" value="true" />
<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category] (Thread:NDC) Message\n
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
%m%n"/>
-->
</layout>
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="WIREFILE" />
</appender>
<!-- ================ -->
<!-- Limit categories -->
<!-- ================ -->
</appender>
<category name="org.jclouds">
<priority value="DEBUG" />
<!-- ================ -->
<!-- Limit categories -->
<!-- ================ -->
<category name="org.jclouds">
<priority value="DEBUG" />
<appender-ref ref="ASYNC" />
</category>
</category>
<category name="jclouds.http.headers">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category><!--
</category>
<category name="jclouds.http.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
--><!-- ======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->
<root>
<priority value="WARN" />
</root>
<!-- ======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->
<root>
<priority value="WARN" />
</root>
</log4j:configuration>

View File

@ -45,7 +45,7 @@ public class BaseContainerIntegrationTest<A, S> extends BaseBlobStoreIntegration
public void containerDoesntExist() {
assert !context.getBlobStore().containerExists("forgetaboutit");
assert !context.getBlobStore().containerExists(
"bog.cloudcachestorefunctionalintegrationtest-first");
"cloudcachestorefunctionalintegrationtest-first");
}
@Test(groups = { "integration", "live" })

View File

@ -40,12 +40,12 @@ import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.S3PropertiesBuilder;
import org.jclouds.aws.s3.blobstore.S3BlobStoreContextBuilder;
import org.jclouds.aws.s3.blobstore.S3BlobStoreContextFactory;
import org.jclouds.azure.storage.blob.AzureBlobPropertiesBuilder;
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStoreContextBuilder;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.BlobStoreContextFactory;
import org.jclouds.rackspace.cloudfiles.CloudFilesPropertiesBuilder;
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStoreContextBuilder;
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStoreContextFactory;
import org.jclouds.twitter.TwitterPropertiesBuilder;
import org.jclouds.util.Utils;
import org.testng.annotations.BeforeClass;
@ -53,7 +53,7 @@ import org.testng.annotations.BeforeTest;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableList;
/**
* Starts up the Google App Engine for Java Development environment and deploys an application which
@ -66,7 +66,7 @@ public class TweetStoreLiveTest {
GoogleDevServer server;
private URL url;
private ImmutableSet<BlobStoreContext<? extends Object, ? extends Object>> contexts;
private Iterable<BlobStoreContext<? extends Object, ? extends Object>> contexts;
private String container;
@BeforeTest
@ -79,11 +79,10 @@ public class TweetStoreLiveTest {
.getProperty(PROPERTY_TWEETSTORE_CONTAINER), PROPERTY_TWEETSTORE_CONTAINER));
props.setProperty(PROPERTY_BLOBSTORE_CONTEXTBUILDERS,
// WATCH THIS.. when adding a new context, you must update the string
// String.format("%s,%s,%s", S3BlobStoreContextBuilder.class.getName(),
// CloudFilesBlobStoreContextBuilder.class.getName(),
// AzureBlobStoreContextBuilder.class.getName()));
String.format("%s,%s", S3BlobStoreContextBuilder.class.getName(),
CloudFilesBlobStoreContextBuilder.class.getName()));
String.format("%s,%s,%s", S3BlobStoreContextBuilder.class.getName(),
CloudFilesBlobStoreContextBuilder.class.getName(),
AzureBlobStoreContextBuilder.class.getName()));
props = new TwitterPropertiesBuilder(props).withCredentials(
checkNotNull(System.getProperty(PROPERTY_TWITTER_USER), PROPERTY_TWITTER_USER),
System.getProperty(PROPERTY_TWITTER_PASSWORD, PROPERTY_TWITTER_PASSWORD)).build();
@ -110,22 +109,22 @@ public class TweetStoreLiveTest {
@BeforeClass
void clearAndCreateContainers() throws InterruptedException, ExecutionException,
TimeoutException {
TimeoutException, IOException {
container = checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER));
BlobStoreContext<?, ?> s3Context = S3BlobStoreContextFactory.createContext(checkNotNull(
System.getProperty(PROPERTY_AWS_ACCESSKEYID), PROPERTY_AWS_ACCESSKEYID), System
BlobStoreContextFactory factory = new BlobStoreContextFactory();
BlobStoreContext<?, ?> s3Context = factory.createContext("s3", checkNotNull(System
.getProperty(PROPERTY_AWS_ACCESSKEYID), PROPERTY_AWS_ACCESSKEYID), System
.getProperty(PROPERTY_AWS_SECRETACCESSKEY, PROPERTY_AWS_SECRETACCESSKEY));
BlobStoreContext<?, ?> cfContext = CloudFilesBlobStoreContextFactory.createContext(
checkNotNull(System.getProperty(PROPERTY_RACKSPACE_USER), PROPERTY_RACKSPACE_USER),
System.getProperty(PROPERTY_RACKSPACE_KEY, PROPERTY_RACKSPACE_KEY));
BlobStoreContext<?, ?> cfContext = factory.createContext("cloudfiles", checkNotNull(System
.getProperty(PROPERTY_RACKSPACE_USER), PROPERTY_RACKSPACE_USER), System.getProperty(
PROPERTY_RACKSPACE_KEY, PROPERTY_RACKSPACE_KEY));
// BlobStoreContext<?, ?> azContext = AzureBlobStoreContextFactory.createContext(checkNotNull(
// System.getProperty(PROPERTY_AZURESTORAGE_ACCOUNT), PROPERTY_AZURESTORAGE_ACCOUNT),
// System.getProperty(PROPERTY_AZURESTORAGE_KEY, PROPERTY_AZURESTORAGE_KEY));
//
// this.contexts = ImmutableSet.of(s3Context, cfContext, azContext);
this.contexts = ImmutableSet.of(s3Context, cfContext);
BlobStoreContext<?, ?> azContext = factory.createContext("azureblob", checkNotNull(System
.getProperty(PROPERTY_AZURESTORAGE_ACCOUNT), PROPERTY_AZURESTORAGE_ACCOUNT), System
.getProperty(PROPERTY_AZURESTORAGE_KEY, PROPERTY_AZURESTORAGE_KEY));
this.contexts = ImmutableList.of(s3Context, cfContext, azContext);
boolean deleted = false;
for (BlobStoreContext<?, ?> context : contexts) {
if (context.getBlobStore().containerExists(container)) {
@ -135,8 +134,8 @@ public class TweetStoreLiveTest {
}
}
if (deleted) {
System.err.println("sleeping 30 seconds to allow containers to clear");
Thread.sleep(30000);
System.err.println("sleeping 60 seconds to allow containers to clear");
Thread.sleep(60000);
}
for (BlobStoreContext<?, ?> context : contexts) {
System.err.printf("creating container %s at %s%n", container, context.getEndPoint());
@ -164,8 +163,7 @@ public class TweetStoreLiveTest {
public void testPrimeContainers() throws IOException, InterruptedException {
URL gurl = new URL(url, "/store/do");
for (String context : new String[] { "S3", "CloudFiles" }) {
// for (String context : new String[] { "S3", "Azure", "CloudFiles" }) {
for (String context : new String[] { "S3", "Azure", "CloudFiles" }) {
System.out.println("storing at context: " + context);
HttpURLConnection connection = (HttpURLConnection) gurl.openConnection();
connection.addRequestProperty("X-AppEngine-QueueName", "twitter");
@ -176,8 +174,8 @@ public class TweetStoreLiveTest {
connection.disconnect();
}
System.err.println("sleeping 10 seconds to allow for eventual consistency delay");
Thread.sleep(10000);
System.err.println("sleeping 20 seconds to allow for eventual consistency delay");
Thread.sleep(20000);
for (BlobStoreContext<?, ?> context : contexts) {
assert context.createInputStreamMap(container).size() > 0 : context.getEndPoint();
}

View File

@ -40,12 +40,12 @@ import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.S3PropertiesBuilder;
import org.jclouds.aws.s3.blobstore.S3BlobStoreContextBuilder;
import org.jclouds.aws.s3.blobstore.S3BlobStoreContextFactory;
import org.jclouds.azure.storage.blob.AzureBlobPropertiesBuilder;
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStoreContextBuilder;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.BlobStoreContextFactory;
import org.jclouds.rackspace.cloudfiles.CloudFilesPropertiesBuilder;
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStoreContextBuilder;
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStoreContextFactory;
import org.jclouds.twitter.TwitterPropertiesBuilder;
import org.jclouds.util.Utils;
import org.testng.annotations.BeforeClass;
@ -53,7 +53,7 @@ import org.testng.annotations.BeforeTest;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableList;
/**
* Starts up the Google App Engine for Java Development environment and deploys an application which
@ -66,7 +66,7 @@ public class TweetStoreLiveTest {
GoogleDevServer server;
private URL url;
private ImmutableSet<BlobStoreContext<? extends Object, ? extends Object>> contexts;
private Iterable<BlobStoreContext<? extends Object, ? extends Object>> contexts;
private String container;
@BeforeTest
@ -79,14 +79,9 @@ public class TweetStoreLiveTest {
.getProperty(PROPERTY_TWEETSTORE_CONTAINER), PROPERTY_TWEETSTORE_CONTAINER));
props.setProperty(PROPERTY_BLOBSTORE_CONTEXTBUILDERS,
// WATCH THIS.. when adding a new context, you must update the string
// String.format("%s,%s,%s", S3BlobStoreContextBuilder.class.getName(),
// CloudFilesBlobStoreContextBuilder.class.getName(),
// AzureBlobStoreContextBuilder.class.getName()));
String.format("%s,%s", S3BlobStoreContextBuilder.class.getName(),
CloudFilesBlobStoreContextBuilder.class.getName()));
props = new TwitterPropertiesBuilder(props).withCredentials(
checkNotNull(System.getProperty(PROPERTY_TWITTER_USER), PROPERTY_TWITTER_USER),
System.getProperty(PROPERTY_TWITTER_PASSWORD, PROPERTY_TWITTER_PASSWORD)).build();
String.format("%s,%s,%s", S3BlobStoreContextBuilder.class.getName(),
CloudFilesBlobStoreContextBuilder.class.getName(),
AzureBlobStoreContextBuilder.class.getName()));
props = new TwitterPropertiesBuilder(props).withCredentials(
checkNotNull(System.getProperty(PROPERTY_TWITTER_USER), PROPERTY_TWITTER_USER),
@ -114,22 +109,22 @@ public class TweetStoreLiveTest {
@BeforeClass
void clearAndCreateContainers() throws InterruptedException, ExecutionException,
TimeoutException {
TimeoutException, IOException {
container = checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER));
BlobStoreContext<?, ?> s3Context = S3BlobStoreContextFactory.createContext(checkNotNull(
System.getProperty(PROPERTY_AWS_ACCESSKEYID), PROPERTY_AWS_ACCESSKEYID), System
BlobStoreContextFactory factory = new BlobStoreContextFactory();
BlobStoreContext<?, ?> s3Context = factory.createContext("s3", checkNotNull(System
.getProperty(PROPERTY_AWS_ACCESSKEYID), PROPERTY_AWS_ACCESSKEYID), System
.getProperty(PROPERTY_AWS_SECRETACCESSKEY, PROPERTY_AWS_SECRETACCESSKEY));
BlobStoreContext<?, ?> cfContext = CloudFilesBlobStoreContextFactory.createContext(
checkNotNull(System.getProperty(PROPERTY_RACKSPACE_USER), PROPERTY_RACKSPACE_USER),
System.getProperty(PROPERTY_RACKSPACE_KEY, PROPERTY_RACKSPACE_KEY));
BlobStoreContext<?, ?> cfContext = factory.createContext("cloudfiles", checkNotNull(System
.getProperty(PROPERTY_RACKSPACE_USER), PROPERTY_RACKSPACE_USER), System.getProperty(
PROPERTY_RACKSPACE_KEY, PROPERTY_RACKSPACE_KEY));
// BlobStoreContext<?, ?> azContext = AzureBlobStoreContextFactory.createContext(checkNotNull(
// System.getProperty(PROPERTY_AZURESTORAGE_ACCOUNT), PROPERTY_AZURESTORAGE_ACCOUNT),
// System.getProperty(PROPERTY_AZURESTORAGE_KEY, PROPERTY_AZURESTORAGE_KEY));
//
// this.contexts = ImmutableSet.of(s3Context, cfContext, azContext);
this.contexts = ImmutableSet.of(s3Context, cfContext);
BlobStoreContext<?, ?> azContext = factory.createContext("azureblob", checkNotNull(System
.getProperty(PROPERTY_AZURESTORAGE_ACCOUNT), PROPERTY_AZURESTORAGE_ACCOUNT), System
.getProperty(PROPERTY_AZURESTORAGE_KEY, PROPERTY_AZURESTORAGE_KEY));
this.contexts = ImmutableList.of(s3Context, cfContext, azContext);
boolean deleted = false;
for (BlobStoreContext<?, ?> context : contexts) {
if (context.getBlobStore().containerExists(container)) {
@ -139,8 +134,8 @@ public class TweetStoreLiveTest {
}
}
if (deleted) {
System.err.println("sleeping 30 seconds to allow containers to clear");
Thread.sleep(30000);
System.err.println("sleeping 60 seconds to allow containers to clear");
Thread.sleep(60000);
}
for (BlobStoreContext<?, ?> context : contexts) {
System.err.printf("creating container %s at %s%n", container, context.getEndPoint());
@ -168,8 +163,7 @@ public class TweetStoreLiveTest {
public void testPrimeContainers() throws IOException, InterruptedException {
URL gurl = new URL(url, "/store/do");
for (String context : new String[] { "S3", "CloudFiles" }) {
// for (String context : new String[] { "S3", "Azure", "CloudFiles" }) {
for (String context : new String[] { "S3", "Azure", "CloudFiles" }) {
System.out.println("storing at context: " + context);
HttpURLConnection connection = (HttpURLConnection) gurl.openConnection();
connection.addRequestProperty("X-AppEngine-QueueName", "twitter");
@ -180,8 +174,8 @@ public class TweetStoreLiveTest {
connection.disconnect();
}
System.err.println("sleeping 10 seconds to allow for eventual consistency delay");
Thread.sleep(10000);
System.err.println("sleeping 20 seconds to allow for eventual consistency delay");
Thread.sleep(20000);
for (BlobStoreContext<?, ?> context : contexts) {
assert context.createInputStreamMap(container).size() > 0 : context.getEndPoint();
}

View File

@ -32,6 +32,7 @@
<packaging>pom</packaging>
<name>jclouds demos project</name>
<modules>
<module>speedtest-azurequeue</module>
<module>gae-tweetstore</module>
<module>gae-tweetstore-spring</module>
</modules>

View File

@ -0,0 +1,24 @@
====
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
====================================================================
====
#
# this is a simple example command line client that creates a queue, then tracks performance of it
# 1. execute 'mvn install' to build the sample
# 2. invoke the jar, passing your azure credentials and the bucket you wish to create
# ex.
# java -jar target/jclouds-speedtest-azurequeue-jar-with-dependencies.jar accountName encodedKey queueName messageCount

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
====================================================================
-->
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-demos-project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>jclouds-speedtest-azurequeue</artifactId>
<name>tests speed of azurequeue</name>
<description>creates a queue and then tests performance against it</description>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-enterprise</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-azure</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>org.jclouds.azure.azurequeue.SpeedTest</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>org.jclouds.azure.azurequeue.SpeedTest</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,151 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.azure.azurequeue;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.queue.AzureQueueAsyncClient;
import org.jclouds.azure.storage.queue.AzureQueueClient;
import org.jclouds.azure.storage.queue.AzureQueueContextFactory;
import org.jclouds.azure.storage.queue.domain.QueueMetadata;
import org.jclouds.enterprise.config.EnterpriseConfigurationModule;
import org.jclouds.logging.config.NullLoggingModule;
import org.jclouds.rest.RestContext;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
/**
* This the Main class of an Application that tests your response time to amazon AzureQueue.
*
* Usage is: java org.jclouds.aws.sqs.SpeedTest \"account\" \"encodedKey\" \"queueName\"
* \"messageCount\"
*
* @author Adrian Cole
*/
public class SpeedTest {
public static int PARAMETERS = 4;
public static String INVALID_SYNTAX = "Invalid number of parameters. Syntax is: \"account\" \"encodedKey\" \"queueName\" \"messageCount\" ";
public static void main(String[] args) throws InterruptedException {
if (args.length < PARAMETERS)
throw new IllegalArgumentException(INVALID_SYNTAX);
boolean isEnterprise = System.getProperties().containsKey("jclouds.enterprise");
// Args
String account = args[0];
String encodedKey = args[1];
String queueName = args[2];
int messageCount = Integer.parseInt(args[3]);
RestContext<AzureQueueAsyncClient, AzureQueueClient> context = isEnterprise ? AzureQueueContextFactory
.createContext(System.getProperties(), account, encodedKey, new NullLoggingModule(),
new EnterpriseConfigurationModule())
: AzureQueueContextFactory.createContext(System.getProperties(), account,
encodedKey, new NullLoggingModule());
try {
if (purgeQueues(queueName, context)) {
System.out.printf("pausing 60 seconds before recreating queues%n");
Thread.sleep(60 * 1000);
}
createQueue(queueName, context);
runTests(queueName, messageCount, isEnterprise ? "enterprise" : "default", context);
} finally {
purgeQueues(queueName, context);
// Close connectons
context.close();
System.exit(0);
}
}
private static void runTests(String queueName, int messageCount, String contextName,
RestContext<AzureQueueAsyncClient, AzureQueueClient> context)
throws InterruptedException {
String message = "1";
long timeOut = messageCount * 200; // minimum rate should be at least 5/second
int complete = 0;
int errors = 0;
long start = System.currentTimeMillis();
// fire off all the messages for the test
Set<ListenableFuture<Void>> responses = Sets.newHashSet();
for (int i = 0; i < messageCount; i++) {
responses.add(context.getAsyncApi().putMessage(queueName, message));
}
do {
Set<ListenableFuture<Void>> retries = Sets.newHashSet();
for (ListenableFuture<Void> response : responses) {
try {
response.get(100, TimeUnit.MILLISECONDS);
complete++;
} catch (ExecutionException e) {
System.err.println(e.getMessage());
errors++;
} catch (TimeoutException e) {
retries.add(response);
}
}
responses = Sets.newHashSet(retries);
} while (responses.size() > 0 && System.currentTimeMillis() < start + timeOut);
long duration = System.currentTimeMillis() - start;
if (duration > timeOut)
System.out.printf("TIMEOUT: context: %s, rate: %f messages/second%n", contextName,
((double) complete) / (duration / 1000.0));
else
System.out.printf("COMPLETE: context: %s, rate: %f messages/second%n", contextName,
((double) complete) / (duration / 1000.0));
System.gc();
System.out.println("pausing 5 seconds before the next run");
Thread.sleep(5000);// let the network quiet down
}
private static void createQueue(String queueName,
RestContext<AzureQueueAsyncClient, AzureQueueClient> nullLoggingDefaultContext) {
System.out.printf("creating queue: %s%n", queueName);
nullLoggingDefaultContext.getApi().createQueue(queueName);
}
private static boolean purgeQueues(String queueName,
RestContext<AzureQueueAsyncClient, AzureQueueClient> nullLoggingDefaultContext) {
boolean deleted = false;
try {
SortedSet<QueueMetadata> result = Sets.newTreeSet(nullLoggingDefaultContext.getApi()
.listQueues(ListOptions.Builder.prefix(queueName)));
if (result.size() >= 1) {
nullLoggingDefaultContext.getApi().deleteQueue(result.last().getName());
System.out.printf("deleted queue: %s%n", queueName);
deleted = true;
}
} catch (Exception e) {
}
return deleted;
}
}