You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ad...@apache.org on 2014/10/04 07:14:42 UTC

[1/3] JCLOUDS-40 unasync azureblob; plus fold otherwise unused azure-common into it.

Repository: jclouds
Updated Branches:
  refs/heads/1.8.x e55f42416 -> 6843e0cbe


http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureAsyncBlobStore.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureAsyncBlobStore.java b/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureAsyncBlobStore.java
deleted file mode 100644
index a0bba9f..0000000
--- a/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureAsyncBlobStore.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azureblob.blobstore;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.util.concurrent.Futures.transform;
-import static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata;
-
-import java.util.List;
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Provider;
-import javax.inject.Singleton;
-
-import org.jclouds.Constants;
-import org.jclouds.azure.storage.domain.BoundedSet;
-import org.jclouds.azureblob.AzureBlobAsyncClient;
-import org.jclouds.azureblob.blobstore.functions.AzureBlobToBlob;
-import org.jclouds.azureblob.blobstore.functions.BlobPropertiesToBlobMetadata;
-import org.jclouds.azureblob.blobstore.functions.BlobToAzureBlob;
-import org.jclouds.azureblob.blobstore.functions.ContainerToResourceMetadata;
-import org.jclouds.azureblob.blobstore.functions.ListBlobsResponseToResourceList;
-import org.jclouds.azureblob.blobstore.functions.ListOptionsToListBlobsOptions;
-import org.jclouds.azureblob.blobstore.strategy.MultipartUploadStrategy;
-import org.jclouds.azureblob.domain.AzureBlob;
-import org.jclouds.azureblob.domain.BlobProperties;
-import org.jclouds.azureblob.domain.ContainerProperties;
-import org.jclouds.azureblob.domain.ListBlobBlocksResponse;
-import org.jclouds.azureblob.domain.ListBlobsResponse;
-import org.jclouds.azureblob.domain.PublicAccess;
-import org.jclouds.azureblob.options.ListBlobsOptions;
-import org.jclouds.blobstore.BlobStoreContext;
-import org.jclouds.blobstore.domain.Blob;
-import org.jclouds.blobstore.domain.BlobMetadata;
-import org.jclouds.blobstore.domain.PageSet;
-import org.jclouds.blobstore.domain.StorageMetadata;
-import org.jclouds.blobstore.domain.internal.PageSetImpl;
-import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
-import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
-import org.jclouds.blobstore.options.CreateContainerOptions;
-import org.jclouds.blobstore.options.ListContainerOptions;
-import org.jclouds.blobstore.options.PutOptions;
-import org.jclouds.blobstore.util.BlobUtils;
-import org.jclouds.collect.Memoized;
-import org.jclouds.domain.Location;
-import org.jclouds.http.options.GetOptions;
-
-import com.google.common.base.Function;
-import com.google.common.base.Supplier;
-import com.google.common.collect.Iterables;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import org.jclouds.io.Payload;
-
-/**
- * @deprecated will be removed in jclouds 1.7, as async interfaces are no longer
- *             supported. Please use {@link AzureBlobStore}
- */
-@Deprecated
-@Singleton
-public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
-   private final AzureBlobAsyncClient async;
-   private final ContainerToResourceMetadata container2ResourceMd;
-   private final ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions;
-   private final ListBlobsResponseToResourceList azure2BlobStoreResourceList;
-   private final AzureBlobToBlob azureBlob2Blob;
-   private final BlobToAzureBlob blob2AzureBlob;
-   private final BlobPropertiesToBlobMetadata blob2BlobMd;
-   private final BlobToHttpGetOptions blob2ObjectGetOptions;
-   private final Provider<MultipartUploadStrategy> multipartUploadStrategy;
-
-
-   @Inject
-   AzureAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
-            @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, Supplier<Location> defaultLocation,
-            @Memoized Supplier<Set<? extends Location>> locations, AzureBlobAsyncClient async,
-            ContainerToResourceMetadata container2ResourceMd,
-            ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,
-            ListBlobsResponseToResourceList azure2BlobStoreResourceList, AzureBlobToBlob azureBlob2Blob,
-            BlobToAzureBlob blob2AzureBlob, BlobPropertiesToBlobMetadata blob2BlobMd,
-            BlobToHttpGetOptions blob2ObjectGetOptions,
-            Provider<MultipartUploadStrategy> multipartUploadStrategy) {
-      super(context, blobUtils, userExecutor, defaultLocation, locations);
-      this.async = checkNotNull(async, "async");
-      this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd");
-      this.blobStore2AzureContainerListOptions = checkNotNull(blobStore2AzureContainerListOptions,
-               "blobStore2AzureContainerListOptions");
-      this.azure2BlobStoreResourceList = checkNotNull(azure2BlobStoreResourceList, "azure2BlobStoreResourceList");
-      this.azureBlob2Blob = checkNotNull(azureBlob2Blob, "azureBlob2Blob");
-      this.blob2AzureBlob = checkNotNull(blob2AzureBlob, "blob2AzureBlob");
-      this.blob2BlobMd = checkNotNull(blob2BlobMd, "blob2BlobMd");
-      this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
-      this.multipartUploadStrategy = checkNotNull(multipartUploadStrategy, "multipartUploadStrategy");
-   }
-
-   /**
-    * This implementation invokes {@link AzureBlobAsyncClient#listContainers} with the
-    * {@link org.jclouds.azure.storage.options.ListOptions#includeMetadata} option.
-    */
-   @Override
-   public ListenableFuture<org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>> list() {
-      return transform(
-                        async.listContainers(includeMetadata()),
-                        new Function<BoundedSet<ContainerProperties>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
-                           public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(
-                                    BoundedSet<ContainerProperties> from) {
-                              return new PageSetImpl<StorageMetadata>(Iterables.transform(from, container2ResourceMd),
-                                       from.getNextMarker());
-                           }
-                        }, userExecutor);
-   }
-
-   /**
-    * This implementation invokes {@link AzureBlobAsyncClient#containerExists}
-    * 
-    * @param container
-    *           container name
-    */
-   @Override
-   public ListenableFuture<Boolean> containerExists(String container) {
-      return async.containerExists(container);
-   }
-
-   /**
-    * This implementation invokes {@link AzureBlobAsyncClient#createContainer}
-    * 
-    * @param location
-    *           ignored
-    * @param container
-    *           container name
-    */
-   @Override
-   public ListenableFuture<Boolean> createContainerInLocation(Location location, String container) {
-      return async.createContainer(container);
-   }
-
-   /**
-    * This implementation invokes {@link AzureBlobAsyncClient#listBucket}
-    * 
-    * @param container
-    *           container name
-    */
-   @Override
-   public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container, ListContainerOptions options) {
-      ListBlobsOptions azureOptions = blobStore2AzureContainerListOptions.apply(options);
-      ListenableFuture<ListBlobsResponse> returnVal = async.listBlobs(container, azureOptions.includeMetadata());
-      return transform(returnVal, azure2BlobStoreResourceList, userExecutor);
-   }
-
-   /**
-    * This implementation invokes {@link AzureBlobAsyncClient#deleteContainer}
-    * 
-    * @param container
-    *           container name
-    */
-   @Override
-   public ListenableFuture<Void> deleteContainer(final String container) {
-      return async.deleteContainer(container);
-   }
-
-   /**
-    * This implementation invokes {@link AzureBlobAsyncClient#getBlob}
-    * 
-    * @param container
-    *           container name
-    * @param key
-    *           blob key
-    */
-   @Override
-   public ListenableFuture<Blob> getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) {
-      GetOptions azureOptions = blob2ObjectGetOptions.apply(options);
-      ListenableFuture<AzureBlob> returnVal = async.getBlob(container, key, azureOptions);
-      return transform(returnVal, azureBlob2Blob, userExecutor);
-   }
-
-   /**
-    * This implementation invokes {@link AzureBlobAsyncClient#putBlob}
-    * 
-    * @param container
-    *           container name
-    * @param blob
-    *           blob
-    */
-   @Override
-   public ListenableFuture<String> putBlob(String container, Blob blob) {
-      return async.putBlob(container, blob2AzureBlob.apply(blob));
-   }
-
-   /**
-    * This implementation invokes {@link AzureBlobAsyncClient#deleteObject}
-    * 
-    * @param container
-    *           container name
-    * @param key
-    *           blob key
-    */
-   @Override
-   public ListenableFuture<Void> removeBlob(String container, String key) {
-      return async.deleteBlob(container, key);
-   }
-
-   /**
-    * This implementation invokes {@link AzureBlobAsyncClient#blobExists}
-    * 
-    * @param container
-    *           bucket name
-    * @param credential
-    *           object key
-    */
-   @Override
-   public ListenableFuture<Boolean> blobExists(String container, String name) {
-      return async.blobExists(container, name);
-   }
-
-   /**
-    * This implementation invokes {@link AzureBlobAsyncClient#putBlock(String, String, String, Payload)}
-    * @param container
-    * @param name
-    * @param blockId
-    * @param object
-    */
-   public ListenableFuture<Void> putBlock(String container, String name, String blockId, Payload object) {
-      return async.putBlock(container, name, blockId, object);
-   }
-
-
-   /**
-    * This implementation invokes {@link AzureBlobAsyncClient#putBlockList(String, String, java.util.List)}
-    * @param container
-    * @param name
-    * @param blockIdList
-    */
-   public ListenableFuture<String> putBlockList(String container, String name, List<String> blockIdList) {
-      return async.putBlockList(container, name, blockIdList);
-   }
-
-   /**
-    * This implementation invokes {@link AzureBlobAsyncClient#getBlockList(String, String)}
-    * @param container
-    * @param name
-    */
-   public ListenableFuture<ListBlobBlocksResponse> getBlockList(String container, String name) {
-      return async.getBlockList(container, name);
-   }
-
-   /**
-    * This implementation invokes {@link AzureBlobAsyncClient#getBlobProperties}
-    * 
-    * @param container
-    *           container name
-    * @param key
-    *           blob key
-    */
-   @Override
-   public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
-      return transform(async.getBlobProperties(container, key), new Function<BlobProperties, BlobMetadata>() {
-         public BlobMetadata apply(BlobProperties from) {
-            return blob2BlobMd.apply(from);
-         }
-      }, userExecutor);
-   }
-
-   @Override
-   protected boolean deleteAndVerifyContainerGone(String container) {
-      // Azure deleteContainer supports deleting empty containers so emulate
-      // deleteIfEmpty by listing.
-      if (!Futures.getUnchecked(list(container)).isEmpty()) {
-         return false;
-      }
-      Futures.getUnchecked(async.deleteContainer(container));
-      return true;
-   }
-
-   @Override
-   public ListenableFuture<String> putBlob(String container, Blob blob, PutOptions options) {
-      if (options.isMultipart()) {
-         throw new UnsupportedOperationException("Multipart upload not supported in AzureAsyncBlobStore");
-      }
-      return putBlob(container, blob);
-   }
-
-   @Override
-   public ListenableFuture<Boolean> createContainerInLocation(Location location, String container,
-            CreateContainerOptions options) {
-      org.jclouds.azureblob.options.CreateContainerOptions createContainerOptions = new org.jclouds.azureblob.options.CreateContainerOptions();
-      if (options.isPublicRead())
-         createContainerOptions.withPublicAccess(PublicAccess.CONTAINER);
-      return async.createContainer(container, createContainerOptions);
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureBlobRequestSigner.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureBlobRequestSigner.java b/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureBlobRequestSigner.java
index 7415981..7a365ed 100644
--- a/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureBlobRequestSigner.java
+++ b/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/AzureBlobRequestSigner.java
@@ -23,7 +23,7 @@ import static org.jclouds.reflect.Reflection2.method;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import org.jclouds.azureblob.AzureBlobAsyncClient;
+import org.jclouds.azureblob.AzureBlobClient;
 import org.jclouds.azureblob.blobstore.functions.BlobToAzureBlob;
 import org.jclouds.azureblob.domain.AzureBlob;
 import org.jclouds.blobstore.BlobRequestSigner;
@@ -53,9 +53,9 @@ public class AzureBlobRequestSigner implements BlobRequestSigner {
       this.processor = checkNotNull(processor, "processor");
       this.blobToBlob = checkNotNull(blobToBlob, "blobToBlob");
       this.blob2HttpGetOptions = checkNotNull(blob2HttpGetOptions, "blob2HttpGetOptions");
-      this.getMethod = method(AzureBlobAsyncClient.class, "getBlob", String.class, String.class, GetOptions[].class);
-      this.deleteMethod = method(AzureBlobAsyncClient.class, "deleteBlob", String.class, String.class);
-      this.createMethod = method(AzureBlobAsyncClient.class, "putBlob", String.class, AzureBlob.class);
+      this.getMethod = method(AzureBlobClient.class, "getBlob", String.class, String.class, GetOptions[].class);
+      this.deleteMethod = method(AzureBlobClient.class, "deleteBlob", String.class, String.class);
+      this.createMethod = method(AzureBlobClient.class, "putBlob", String.class, AzureBlob.class);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/config/AzureBlobStoreContextModule.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/config/AzureBlobStoreContextModule.java b/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/config/AzureBlobStoreContextModule.java
index dce2e58..aef156d 100644
--- a/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/config/AzureBlobStoreContextModule.java
+++ b/providers/azureblob/src/main/java/org/jclouds/azureblob/blobstore/config/AzureBlobStoreContextModule.java
@@ -21,7 +21,6 @@ import java.util.concurrent.TimeUnit;
 import javax.inject.Singleton;
 
 import org.jclouds.azureblob.AzureBlobClient;
-import org.jclouds.azureblob.blobstore.AzureAsyncBlobStore;
 import org.jclouds.azureblob.blobstore.AzureBlobRequestSigner;
 import org.jclouds.azureblob.blobstore.AzureBlobStore;
 import org.jclouds.azureblob.domain.PublicAccess;
@@ -29,6 +28,7 @@ import org.jclouds.blobstore.AsyncBlobStore;
 import org.jclouds.blobstore.BlobRequestSigner;
 import org.jclouds.blobstore.BlobStore;
 import org.jclouds.blobstore.attr.ConsistencyModel;
+import org.jclouds.blobstore.internal.SubmissionAsyncBlobStore;
 
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
@@ -37,15 +37,12 @@ import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
 import com.google.inject.Scopes;
 
-/**
- * Configures the {@link AzureBlobStoreContext}; requires {@link AzureAsyncBlobStore} bound.
- */
 public class AzureBlobStoreContextModule extends AbstractModule {
 
    @Override
    protected void configure() {
       bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT);
-      bind(AsyncBlobStore.class).to(AzureAsyncBlobStore.class).in(Scopes.SINGLETON);
+      bind(AsyncBlobStore.class).to(SubmissionAsyncBlobStore.class).in(Scopes.SINGLETON);
       bind(BlobStore.class).to(AzureBlobStore.class).in(Scopes.SINGLETON);
       bind(BlobRequestSigner.class).to(AzureBlobRequestSigner.class);
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azureblob/config/AzureBlobHttpApiModule.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azureblob/config/AzureBlobHttpApiModule.java b/providers/azureblob/src/main/java/org/jclouds/azureblob/config/AzureBlobHttpApiModule.java
new file mode 100644
index 0000000..52a4195
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azureblob/config/AzureBlobHttpApiModule.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azureblob.config;
+
+import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
+import static org.jclouds.json.config.GsonModule.DateAdapter;
+import static org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
+
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Named;
+
+import org.jclouds.azure.storage.handlers.AzureStorageClientErrorRetryHandler;
+import org.jclouds.azureblob.AzureBlobClient;
+import org.jclouds.azureblob.handlers.ParseAzureBlobErrorFromXmlContent;
+import org.jclouds.date.DateService;
+import org.jclouds.date.TimeStamp;
+import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.HttpRetryHandler;
+import org.jclouds.http.annotation.ClientError;
+import org.jclouds.http.annotation.Redirection;
+import org.jclouds.http.annotation.ServerError;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.inject.Provides;
+
+/**
+ * Configures the Azure Blob Service connection, including logging and http transport.
+ */
+@ConfiguresHttpApi
+public class AzureBlobHttpApiModule extends HttpApiModule<AzureBlobClient> {
+
+   @Override
+   protected void configure() {
+      install(new AzureBlobModule());
+      bind(DateAdapter.class).to(Iso8601DateAdapter.class);
+      super.configure();
+   }
+
+   @Provides
+   @TimeStamp
+   protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
+      return cache.get();
+   }
+
+   /**
+    * borrowing concurrency code to ensure that caching takes place properly
+    */
+   @Provides
+   @TimeStamp
+   protected Supplier<String> provideTimeStampCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
+         final DateService dateService) {
+      return Suppliers.memoizeWithExpiration(new Supplier<String>() {
+         public String get() {
+            return dateService.rfc822DateFormat();
+         }
+      }, seconds, TimeUnit.SECONDS);
+   }
+
+   @Override
+   protected void bindRetryHandlers() {
+      bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(AzureStorageClientErrorRetryHandler.class);
+   }
+
+   @Override
+   protected void bindErrorHandlers() {
+      bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseAzureBlobErrorFromXmlContent.class);
+      bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseAzureBlobErrorFromXmlContent.class);
+      bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseAzureBlobErrorFromXmlContent.class);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azureblob/config/AzureBlobRestClientModule.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azureblob/config/AzureBlobRestClientModule.java b/providers/azureblob/src/main/java/org/jclouds/azureblob/config/AzureBlobRestClientModule.java
deleted file mode 100644
index 4b62ebf..0000000
--- a/providers/azureblob/src/main/java/org/jclouds/azureblob/config/AzureBlobRestClientModule.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azureblob.config;
-
-import org.jclouds.azure.storage.config.AzureStorageRestClientModule;
-import org.jclouds.azureblob.AzureBlobAsyncClient;
-import org.jclouds.azureblob.AzureBlobClient;
-import org.jclouds.azureblob.handlers.ParseAzureBlobErrorFromXmlContent;
-import org.jclouds.http.HttpErrorHandler;
-import org.jclouds.http.annotation.ClientError;
-import org.jclouds.http.annotation.Redirection;
-import org.jclouds.http.annotation.ServerError;
-import org.jclouds.rest.ConfiguresRestClient;
-
-/**
- * Configures the Azure Blob Service connection, including logging and http transport.
- */
-@ConfiguresRestClient
-public class AzureBlobRestClientModule extends AzureStorageRestClientModule<AzureBlobClient, AzureBlobAsyncClient> {
-
-   @Override
-   protected void configure() {
-      install(new AzureBlobModule());
-      super.configure();
-   }
-
-   @Override
-   protected void bindErrorHandlers() {
-      bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseAzureBlobErrorFromXmlContent.class);
-      bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseAzureBlobErrorFromXmlContent.class);
-      bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseAzureBlobErrorFromXmlContent.class);
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/test/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthenticationTest.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/test/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthenticationTest.java b/providers/azureblob/src/test/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthenticationTest.java
new file mode 100644
index 0000000..5bea836
--- /dev/null
+++ b/providers/azureblob/src/test/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthenticationTest.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.filters;
+
+import static org.jclouds.reflect.Reflection2.typeToken;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URI;
+
+import javax.ws.rs.HttpMethod;
+
+import org.jclouds.ContextBuilder;
+import org.jclouds.azure.storage.config.AzureStorageRestClientModule;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.IntegrationTestAsyncClient;
+import org.jclouds.http.IntegrationTestClient;
+import org.jclouds.logging.config.NullLoggingModule;
+import org.jclouds.rest.AnonymousRestApiMetadata;
+import org.jclouds.rest.internal.BaseRestApiTest.MockModule;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.net.HttpHeaders;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+
+@Test(groups = "unit")
+public class SharedKeyLiteAuthenticationTest {
+
+   private static final String ACCOUNT = "foo";
+   private Injector injector;
+   private SharedKeyLiteAuthentication filter;
+
+   @DataProvider(parallel = true)
+   public Object[][] dataProvider() {
+      return new Object[][] {
+            { HttpRequest.builder().method(HttpMethod.PUT).endpoint("http://" + ACCOUNT
+                  + ".blob.core.windows.net/movies/MOV1.avi?comp=block&blockid=BlockId1&timeout=60").build() },
+            { HttpRequest.builder().method(HttpMethod.PUT).endpoint("http://" + ACCOUNT
+                  + ".blob.core.windows.net/movies/MOV1.avi?comp=blocklist&timeout=120").build() },
+            { HttpRequest.builder().method(HttpMethod.GET).endpoint("http://" + ACCOUNT + ".blob.core.windows.net/movies/MOV1.avi").build() } };
+   }
+
+   /**
+    * NOTE this test is dependent on how frequently the timestamp updates. At
+    * the time of writing, this was once per second. If this timestamp update
+    * interval is increased, it could make this test appear to hang for a long
+    * time.
+    */
+   @Test(threadPoolSize = 3, dataProvider = "dataProvider", timeOut = 3000)
+   void testIdempotent(HttpRequest request) {
+      request = filter.filter(request);
+      String signature = request.getFirstHeaderOrNull(HttpHeaders.AUTHORIZATION);
+      String date = request.getFirstHeaderOrNull(HttpHeaders.DATE);
+      int iterations = 1;
+      while (request.getFirstHeaderOrNull(HttpHeaders.DATE).equals(date)) {
+         date = request.getFirstHeaderOrNull(HttpHeaders.DATE);
+         iterations++;
+         assertEquals(signature, request.getFirstHeaderOrNull(HttpHeaders.AUTHORIZATION));
+         request = filter.filter(request);
+      }
+      System.out.printf("%s: %d iterations before the timestamp updated %n", Thread.currentThread().getName(),
+            iterations);
+   }
+
+   @Test
+   void testAclQueryStringRoot() {
+      URI host = URI.create("http://" + ACCOUNT + ".blob.core.windows.net/?comp=list");
+      HttpRequest request = HttpRequest.builder().method(HttpMethod.GET).endpoint(host).build();
+      StringBuilder builder = new StringBuilder();
+      filter.appendUriPath(request, builder);
+      assertEquals(builder.toString(), "/?comp=list");
+   }
+
+   @Test
+   void testAclQueryStringResTypeNotSignificant() {
+      URI host = URI.create("http://" + ACCOUNT + ".blob.core.windows.net/mycontainer?restype=container");
+      HttpRequest request = HttpRequest.builder().method(HttpMethod.GET).endpoint(host).build();
+      StringBuilder builder = new StringBuilder();
+      filter.appendUriPath(request, builder);
+      assertEquals(builder.toString(), "/mycontainer");
+   }
+
+   @Test
+   void testAclQueryStringComp() {
+      URI host = URI.create("http://" + ACCOUNT + ".blob.core.windows.net/mycontainer?comp=list");
+      HttpRequest request = HttpRequest.builder().method(HttpMethod.GET).endpoint(host).build();
+      StringBuilder builder = new StringBuilder();
+      filter.appendUriPath(request, builder);
+      assertEquals(builder.toString(), "/mycontainer?comp=list");
+   }
+
+   @Test
+   void testAclQueryStringRelativeWithExtraJunk() {
+      URI host = URI.create("http://" + ACCOUNT
+            + ".blob.core.windows.net/mycontainer?comp=list&marker=marker&maxresults=1&prefix=prefix");
+      HttpRequest request = HttpRequest.builder().method(HttpMethod.GET).endpoint(host).build();
+      StringBuilder builder = new StringBuilder();
+      filter.appendUriPath(request, builder);
+      assertEquals(builder.toString(), "/mycontainer?comp=list");
+   }
+
+   /**
+    * before class, as we need to ensure that the filter is threadsafe.
+    * 
+    * @throws IOException
+    * 
+    */
+   @BeforeClass
+   protected void createFilter() throws IOException {
+      injector = ContextBuilder
+            .newBuilder(
+                  AnonymousRestApiMetadata
+                        .forClientMappedToAsyncClient(IntegrationTestClient.class, IntegrationTestAsyncClient.class)
+                        .toBuilder().build())
+            .endpoint("https://${jclouds.identity}.blob.core.windows.net")
+            .credentials(ACCOUNT, "credential")
+            .modules(
+                  ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule(),
+                        new AzureStorageRestClientModule<IntegrationTestClient, IntegrationTestAsyncClient>(
+                              typeToken(IntegrationTestClient.class), typeToken(IntegrationTestAsyncClient.class))))
+            .buildInjector();
+      filter = injector.getInstance(SharedKeyLiteAuthentication.class);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/test/java/org/jclouds/azure/storage/handlers/ParseAzureErrorFromXmlContentTest.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/test/java/org/jclouds/azure/storage/handlers/ParseAzureErrorFromXmlContentTest.java b/providers/azureblob/src/test/java/org/jclouds/azure/storage/handlers/ParseAzureErrorFromXmlContentTest.java
new file mode 100644
index 0000000..5cfbffe
--- /dev/null
+++ b/providers/azureblob/src/test/java/org/jclouds/azure/storage/handlers/ParseAzureErrorFromXmlContentTest.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.handlers;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reportMatcher;
+import static org.easymock.EasyMock.verify;
+
+import java.net.URI;
+
+import org.easymock.IArgumentMatcher;
+import org.jclouds.azure.storage.AzureStorageResponseException;
+import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.config.SaxParserModule;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+
+@Test(groups = { "unit" })
+public class ParseAzureErrorFromXmlContentTest {
+
+   @Test
+   public void test411WithTextHtmlIllegalArgumentException() {
+      assertCodeMakes("PUT",
+            URI.create("https://jclouds.blob.core.windows.net/adriancole-azureblob-413790770?restype=container"), 411,
+            "Length Required", "text/html; charset=us-ascii", "<HTML><HEAD><TITLE>Length Required</TITLE>\r\n",
+            IllegalArgumentException.class);
+   }
+
+   @Test
+   public void test304WithNoContentIllegalArgumentException() {
+      assertCodeMakes("GET", URI.create("https://jclouds.blob.core.windows.net/adriancole-blobstore0/apples"), 411,
+            "HTTP/1.1 304 The condition specified using HTTP conditional header(s) is not met.", "application/unknown",
+            "", IllegalArgumentException.class);
+   }
+
+   
+   @Test
+   public void test412WithTextHtmlHttpResponseException() {
+      assertCodeMakes(
+            "GET",
+            URI.create("https://jclouds.blob.core.windows.net/adriancole-blobstore2?restype=container&comp=list&prefix=apps/apps/apps/&include=metadata"),
+            412,
+            "HTTP/1.1 412 The condition specified using HTTP conditional header(s) is not met.",
+            "application/xml",
+            "<?xml version=\"1.0\" encoding=\"utf-8\"?><Error><Code>ConditionNotMet</Code><Message>The condition specified using HTTP conditional header(s) is not met.\nRequestId:921efcad-84bc-4e0a-863d-24810d1096e1\nTime:2010-11-04T15:03:07.8694513Z</Message></Error>",
+            AzureStorageResponseException.class);
+   }
+
+   private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
+         String content, Class<? extends Exception> expected) {
+
+      ParseAzureStorageErrorFromXmlContent function = Guice.createInjector(new SaxParserModule(), new AbstractModule() {
+
+         @Override
+         protected void configure() {
+            bind(SharedKeyLiteAuthentication.class).toInstance(createMock(SharedKeyLiteAuthentication.class));
+         }
+
+      }).getInstance(ParseAzureStorageErrorFromXmlContent.class);
+
+      HttpCommand command = createMock(HttpCommand.class);
+      HttpRequest request = HttpRequest.builder().method(method).endpoint(uri).build();
+      HttpResponse response = HttpResponse.builder().statusCode(statusCode).message(message).payload(content).build();
+      response.getPayload().getContentMetadata().setContentType(contentType);
+
+      expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
+      command.setException(classEq(expected));
+
+      replay(command);
+
+      function.handleError(command, response);
+
+      verify(command);
+   }
+
+   public static Exception classEq(final Class<? extends Exception> in) {
+      reportMatcher(new IArgumentMatcher() {
+
+         @Override
+         public void appendTo(StringBuffer buffer) {
+            buffer.append("classEq(");
+            buffer.append(in);
+            buffer.append(")");
+         }
+
+         @Override
+         public boolean matches(Object arg) {
+            return arg.getClass() == in;
+         }
+
+      });
+      return null;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/test/java/org/jclouds/azure/storage/options/CreateOptionsTest.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/test/java/org/jclouds/azure/storage/options/CreateOptionsTest.java b/providers/azureblob/src/test/java/org/jclouds/azure/storage/options/CreateOptionsTest.java
new file mode 100644
index 0000000..b582783
--- /dev/null
+++ b/providers/azureblob/src/test/java/org/jclouds/azure/storage/options/CreateOptionsTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.options;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.azure.storage.reference.AzureStorageHeaders;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMultimap;
+
+/**
+ * Tests behavior of {@code CreateOptions}
+ */
+@Test(groups = "unit")
+public class CreateOptionsTest {
+
+   public void testMetadata() {
+      CreateOptions options = new CreateOptions().withMetadata(ImmutableMultimap.of(
+               "test", "foo"));
+      assertEquals(ImmutableList.of("foo"), options.buildRequestHeaders().get(
+               AzureStorageHeaders.USER_METADATA_PREFIX + "test"));
+   }
+
+   public void testMetadataAlreadyPrefixed() {
+      CreateOptions options = new CreateOptions().withMetadata(ImmutableMultimap.of(
+               AzureStorageHeaders.USER_METADATA_PREFIX + "test", "foo"));
+      assertEquals(ImmutableList.of("foo"), options.buildRequestHeaders().get(
+               AzureStorageHeaders.USER_METADATA_PREFIX + "test"));
+   }
+
+   public void testMetadataStatic() {
+      CreateOptions options = CreateOptions.Builder.withMetadata(ImmutableMultimap.of(
+               "test", "foo"));
+      assertEquals(ImmutableList.of("foo"), options.buildRequestHeaders().get(
+               AzureStorageHeaders.USER_METADATA_PREFIX + "test"));
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/test/java/org/jclouds/azure/storage/options/ListOptionsTest.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/test/java/org/jclouds/azure/storage/options/ListOptionsTest.java b/providers/azureblob/src/test/java/org/jclouds/azure/storage/options/ListOptionsTest.java
new file mode 100644
index 0000000..67fc768
--- /dev/null
+++ b/providers/azureblob/src/test/java/org/jclouds/azure/storage/options/ListOptionsTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.options;
+
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Tests behavior of {@code ListOptions}
+ */
+@Test(groups = "unit")
+public class ListOptionsTest {
+   public void testIncludeMetadata() {
+      ListOptions options = new ListOptions().includeMetadata();
+      assertEquals(ImmutableList.of("metadata"), options.buildQueryParameters().get("include"));
+   }
+
+   public void testIncludeMetadataStatic() {
+      ListOptions options = ListOptions.Builder.includeMetadata();
+      assertEquals(ImmutableList.of("metadata"), options.buildQueryParameters().get("include"));
+   }
+
+   public void testPrefix() {
+      ListOptions options = new ListOptions().prefix("a");
+      assertEquals(ImmutableList.of("a"), options.buildQueryParameters().get("prefix"));
+   }
+
+   public void testMarker() {
+      ListOptions options = new ListOptions().marker("a");
+      assertEquals(ImmutableList.of("a"), options.buildQueryParameters().get("marker"));
+   }
+
+   public void testMaxResults() {
+      int limit = 1;
+      ListOptions options = new ListOptions().maxResults(limit);
+      assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("maxresults"));
+   }
+
+   public void testPrefixStatic() {
+      ListOptions options = ListOptions.Builder.prefix("a");
+      assertEquals(ImmutableList.of("a"), options.buildQueryParameters().get("prefix"));
+   }
+
+   public void testMarkerStatic() {
+      ListOptions options = ListOptions.Builder.marker("a");
+      assertEquals(ImmutableList.of("a"), options.buildQueryParameters().get("marker"));
+   }
+
+   public void testMaxResultsStatic() {
+      int limit = 1;
+      ListOptions options = ListOptions.Builder.maxResults(limit);
+      assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("maxresults"));
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/test/java/org/jclouds/azure/storage/xml/ErrorHandlerTest.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/test/java/org/jclouds/azure/storage/xml/ErrorHandlerTest.java b/providers/azureblob/src/test/java/org/jclouds/azure/storage/xml/ErrorHandlerTest.java
new file mode 100644
index 0000000..1698cd6
--- /dev/null
+++ b/providers/azureblob/src/test/java/org/jclouds/azure/storage/xml/ErrorHandlerTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.xml;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+
+import org.jclouds.azure.storage.domain.AzureStorageError;
+import org.jclouds.http.functions.BaseHandlerTest;
+import org.jclouds.http.functions.ParseSax;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code ErrorHandler}
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "ErrorHandlerTest")
+public class ErrorHandlerTest extends BaseHandlerTest {
+
+   ParseSax<AzureStorageError> createParser() {
+      ParseSax<AzureStorageError> parser = factory.create(injector
+               .getInstance(ErrorHandler.class));
+      return parser;
+   }
+
+   public void testApplyInputStream() {
+      InputStream is = getClass().getResourceAsStream("/test_error.xml");
+      ParseSax<AzureStorageError> parser = createParser();
+      AzureStorageError result = parser.parse(is);
+      assertEquals(result.getCode(), "AuthenticationFailed");
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/test/java/org/jclouds/azureblob/AzureBlobAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/test/java/org/jclouds/azureblob/AzureBlobAsyncClientTest.java b/providers/azureblob/src/test/java/org/jclouds/azureblob/AzureBlobAsyncClientTest.java
deleted file mode 100644
index 5928175..0000000
--- a/providers/azureblob/src/test/java/org/jclouds/azureblob/AzureBlobAsyncClientTest.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azureblob;
-
-import static org.jclouds.azure.storage.options.ListOptions.Builder.maxResults;
-import static org.jclouds.azureblob.options.CreateContainerOptions.Builder.withPublicAccess;
-import static org.jclouds.reflect.Reflection2.method;
-import static org.testng.Assert.assertEquals;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.jclouds.Fallbacks.TrueOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
-import org.jclouds.azure.storage.options.ListOptions;
-import org.jclouds.azureblob.AzureBlobFallbacks.FalseIfContainerAlreadyExists;
-import org.jclouds.azureblob.domain.PublicAccess;
-import org.jclouds.azureblob.functions.ParseBlobFromHeadersAndHttpContent;
-import org.jclouds.azureblob.functions.ParseContainerPropertiesFromHeaders;
-import org.jclouds.azureblob.functions.ParsePublicAccessHeader;
-import org.jclouds.azureblob.options.CreateContainerOptions;
-import org.jclouds.azureblob.options.ListBlobsOptions;
-import org.jclouds.azureblob.xml.AccountNameEnumerationResultsHandler;
-import org.jclouds.azureblob.xml.ContainerNameEnumerationResultsHandler;
-import org.jclouds.blobstore.BlobStoreFallbacks.NullOnContainerNotFound;
-import org.jclouds.blobstore.BlobStoreFallbacks.NullOnKeyNotFound;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.http.functions.ReleasePayloadAndReturn;
-import org.jclouds.http.functions.ReturnTrueIf2xx;
-import org.jclouds.http.options.GetOptions;
-import org.jclouds.rest.internal.BaseAsyncClientTest;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code AzureBlobAsyncClient}
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "AzureBlobAsyncClientTest")
-public class AzureBlobAsyncClientTest extends BaseAsyncClientTest<AzureBlobAsyncClient> {
-
-   public void testListContainers() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "listContainers", ListOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of());
-
-      assertRequestLineEquals(request, "GET https://identity.blob.core.windows.net/?comp=list HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, AccountNameEnumerationResultsHandler.class);
-      assertFallbackClassEquals(method, null);
-
-   }
-
-   public void testListContainersOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "listContainers", ListOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(maxResults(1).marker("marker").prefix("prefix")));
-
-      assertRequestLineEquals(request,
-               "GET https://identity.blob.core.windows.net/?comp=list&maxresults=1&marker=marker&prefix=prefix HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, AccountNameEnumerationResultsHandler.class);
-      assertFallbackClassEquals(method, null);
-   }
-
-   public void testCreateContainer() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "createContainer", String.class,
-               CreateContainerOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container"));
-
-      assertRequestLineEquals(request,
-               "PUT https://identity.blob.core.windows.net/container?restype=container HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, FalseIfContainerAlreadyExists.class);
-   }
-
-   public void testDeleteContainer() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "deleteContainer", String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container"));
-
-      assertRequestLineEquals(request,
-               "DELETE https://identity.blob.core.windows.net/container?restype=container HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, VoidOnNotFoundOr404.class);
-   }
-
-   public void testCreateContainerOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "createContainer", String.class,
-               CreateContainerOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container", withPublicAccess(PublicAccess.BLOB)
-               .withMetadata(ImmutableMultimap.of("foo", "bar"))));
-
-      assertRequestLineEquals(request,
-               "PUT https://identity.blob.core.windows.net/container?restype=container HTTP/1.1");
-      assertNonPayloadHeadersEqual(request,
-               "x-ms-blob-public-access: blob\nx-ms-meta-foo: bar\nx-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, FalseIfContainerAlreadyExists.class);
-   }
-
-   public void testCreateRootContainer() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "createRootContainer", CreateContainerOptions[].class);
-
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of());
-
-      assertRequestLineEquals(request, "PUT https://identity.blob.core.windows.net/$root?restype=container HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, FalseIfContainerAlreadyExists.class);
-   }
-
-   public void testDeleteRootContainer() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "deleteRootContainer");
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of());
-
-      assertRequestLineEquals(request, "DELETE https://identity.blob.core.windows.net/$root?restype=container HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, TrueOnNotFoundOr404.class);
-   }
-
-   public void testCreateRootContainerOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "createRootContainer", CreateContainerOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(withPublicAccess(PublicAccess.BLOB).withMetadata(
-               ImmutableMultimap.of("foo", "bar"))));
-
-      assertRequestLineEquals(request, "PUT https://identity.blob.core.windows.net/$root?restype=container HTTP/1.1");
-      assertNonPayloadHeadersEqual(request,
-               "x-ms-blob-public-access: blob\nx-ms-meta-foo: bar\nx-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, FalseIfContainerAlreadyExists.class);
-   }
-
-   public void testListBlobs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "listBlobs", String.class, ListBlobsOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container"));
-
-      assertRequestLineEquals(request,
-               "GET https://identity.blob.core.windows.net/container?restype=container&comp=list HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ContainerNameEnumerationResultsHandler.class);
-      assertFallbackClassEquals(method, null);
-   }
-
-   public void testListRootBlobs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "listBlobs", ListBlobsOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of());
-
-      assertRequestLineEquals(request,
-               "GET https://identity.blob.core.windows.net/$root?restype=container&comp=list HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ContainerNameEnumerationResultsHandler.class);
-      assertFallbackClassEquals(method, null);
-   }
-
-   public void testContainerProperties() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "getContainerProperties", String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container"));
-
-      assertRequestLineEquals(request,
-               "HEAD https://identity.blob.core.windows.net/container?restype=container HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ParseContainerPropertiesFromHeaders.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, NullOnContainerNotFound.class);
-   }
-
-   public void testGetPublicAccessForContainer() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "getPublicAccessForContainer", String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container"));
-
-      assertRequestLineEquals(request,
-               "HEAD https://identity.blob.core.windows.net/container?restype=container&comp=acl HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ParsePublicAccessHeader.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, NullOnContainerNotFound.class);
-   }
-
-   public void testSetResourceMetadata() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "setResourceMetadata", String.class, Map.class);
-      GeneratedHttpRequest request = processor.createRequest(method,
-            ImmutableList.<Object> of("container", ImmutableMap.of("key", "value")));
-
-      assertRequestLineEquals(request,
-               "PUT https://identity.blob.core.windows.net/container?restype=container&comp=metadata HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "x-ms-meta-key: value\nx-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-   }
-
-   public void testGetBlob() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "getBlob", String.class, String.class, GetOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container", "blob"));
-
-      assertRequestLineEquals(request, "GET https://identity.blob.core.windows.net/container/blob HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ParseBlobFromHeadersAndHttpContent.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, NullOnKeyNotFound.class);
-   }
-
-   public void testSetBlobMetadata() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AzureBlobAsyncClient.class, "setBlobMetadata", String.class, String.class, Map.class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container", "blob", ImmutableMap.of("key", "value")));
-
-      assertRequestLineEquals(request,
-               "PUT https://identity.blob.core.windows.net/container/blob?comp=metadata HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "x-ms-meta-key: value\nx-ms-version: 2009-09-19\n");
-      assertPayloadEquals(request, null, null, false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-   }
-
-   @Override
-   protected void checkFilters(HttpRequest request) {
-      assertEquals(request.getFilters().size(), 1);
-      assertEquals(request.getFilters().get(0).getClass(), SharedKeyLiteAuthentication.class);
-   }
-
-   @Override
-   public AzureBlobProviderMetadata createProviderMetadata() {
-      return new AzureBlobProviderMetadata();
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/test/java/org/jclouds/azureblob/AzureBlobClientLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/test/java/org/jclouds/azureblob/AzureBlobClientLiveTest.java b/providers/azureblob/src/test/java/org/jclouds/azureblob/AzureBlobClientLiveTest.java
index 836d7de..831eceb 100644
--- a/providers/azureblob/src/test/java/org/jclouds/azureblob/AzureBlobClientLiveTest.java
+++ b/providers/azureblob/src/test/java/org/jclouds/azureblob/AzureBlobClientLiveTest.java
@@ -30,7 +30,6 @@ import java.security.SecureRandom;
 import java.util.Arrays;
 import java.util.Set;
 
-import com.google.common.io.BaseEncoding;
 import org.jclouds.azure.storage.AzureStorageResponseException;
 import org.jclouds.azure.storage.domain.BoundedSet;
 import org.jclouds.azure.storage.options.ListOptions;
@@ -55,10 +54,8 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.Iterables;
 import com.google.common.hash.Hashing;
+import com.google.common.io.BaseEncoding;
 
-/**
- * Tests behavior of {@code AzureBlobClient}
- */
 @Test(groups = "live", singleThreaded = true)
 public class AzureBlobClientLiveTest extends BaseBlobStoreIntegrationTest {
    public AzureBlobClientLiveTest() {
@@ -66,7 +63,7 @@ public class AzureBlobClientLiveTest extends BaseBlobStoreIntegrationTest {
    }
 
    public AzureBlobClient getApi() {
-      return view.unwrap(AzureBlobApiMetadata.CONTEXT_TOKEN).getApi();
+      return view.unwrapApi(AzureBlobClient.class);
    }
 
    @Test
@@ -100,8 +97,8 @@ public class AzureBlobClientLiveTest extends BaseBlobStoreIntegrationTest {
       long containerCount = response.size();
       assertTrue(containerCount >= 1);
       ListBlobsResponse list = getApi().listBlobs(privateContainer);
-      assertEquals(list.getUrl(), URI.create(String.format("https://%s.blob.core.windows.net/%s", view.unwrap(
-               AzureBlobApiMetadata.CONTEXT_TOKEN).getIdentity(), privateContainer)));
+      assertEquals(list.getUrl(), URI.create(String.format("https://%s.blob.core.windows.net/%s",
+            view.unwrap().getIdentity(), privateContainer)));
       // TODO .. check to see the container actually exists
    }
 
@@ -156,8 +153,8 @@ public class AzureBlobClientLiveTest extends BaseBlobStoreIntegrationTest {
          }
       }
       ListBlobsResponse list = getApi().listBlobs();
-      assertEquals(list.getUrl(), URI.create(String.format("https://%s.blob.core.windows.net/$root", view.unwrap(
-               AzureBlobApiMetadata.CONTEXT_TOKEN).getIdentity())));
+      assertEquals(list.getUrl(), URI.create(String.format("https://%s.blob.core.windows.net/$root",
+            view.unwrap().getIdentity())));
    }
 
    @Test

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/test/java/org/jclouds/azureblob/AzureBlobClientTest.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/test/java/org/jclouds/azureblob/AzureBlobClientTest.java b/providers/azureblob/src/test/java/org/jclouds/azureblob/AzureBlobClientTest.java
new file mode 100644
index 0000000..564705c
--- /dev/null
+++ b/providers/azureblob/src/test/java/org/jclouds/azureblob/AzureBlobClientTest.java
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azureblob;
+
+import static org.jclouds.azure.storage.options.ListOptions.Builder.maxResults;
+import static org.jclouds.azureblob.options.CreateContainerOptions.Builder.withPublicAccess;
+import static org.jclouds.reflect.Reflection2.method;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.jclouds.Fallbacks.TrueOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
+import org.jclouds.azure.storage.options.ListOptions;
+import org.jclouds.azureblob.AzureBlobFallbacks.FalseIfContainerAlreadyExists;
+import org.jclouds.azureblob.domain.PublicAccess;
+import org.jclouds.azureblob.functions.ParseBlobFromHeadersAndHttpContent;
+import org.jclouds.azureblob.functions.ParseContainerPropertiesFromHeaders;
+import org.jclouds.azureblob.functions.ParsePublicAccessHeader;
+import org.jclouds.azureblob.options.CreateContainerOptions;
+import org.jclouds.azureblob.options.ListBlobsOptions;
+import org.jclouds.azureblob.xml.AccountNameEnumerationResultsHandler;
+import org.jclouds.azureblob.xml.ContainerNameEnumerationResultsHandler;
+import org.jclouds.blobstore.BlobStoreFallbacks.NullOnContainerNotFound;
+import org.jclouds.blobstore.BlobStoreFallbacks.NullOnKeyNotFound;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.http.functions.ReturnTrueIf2xx;
+import org.jclouds.http.options.GetOptions;
+import org.jclouds.rest.internal.BaseAsyncClientTest;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.reflect.Invokable;
+
+@Test(groups = "unit", testName = "AzureBlobClientTest")
+public class AzureBlobClientTest extends BaseAsyncClientTest<AzureBlobClient> {
+
+   public void testListContainers() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "listContainers", ListOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of());
+
+      assertRequestLineEquals(request, "GET https://identity.blob.core.windows.net/?comp=list HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, AccountNameEnumerationResultsHandler.class);
+      assertFallbackClassEquals(method, null);
+
+   }
+
+   public void testListContainersOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "listContainers", ListOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(maxResults(1).marker("marker").prefix("prefix")));
+
+      assertRequestLineEquals(request,
+               "GET https://identity.blob.core.windows.net/?comp=list&maxresults=1&marker=marker&prefix=prefix HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, AccountNameEnumerationResultsHandler.class);
+      assertFallbackClassEquals(method, null);
+   }
+
+   public void testCreateContainer() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "createContainer", String.class,
+               CreateContainerOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container"));
+
+      assertRequestLineEquals(request,
+               "PUT https://identity.blob.core.windows.net/container?restype=container HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, FalseIfContainerAlreadyExists.class);
+   }
+
+   public void testDeleteContainer() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "deleteContainer", String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container"));
+
+      assertRequestLineEquals(request,
+               "DELETE https://identity.blob.core.windows.net/container?restype=container HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, VoidOnNotFoundOr404.class);
+   }
+
+   public void testCreateContainerOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "createContainer", String.class,
+               CreateContainerOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container", withPublicAccess(PublicAccess.BLOB)
+               .withMetadata(ImmutableMultimap.of("foo", "bar"))));
+
+      assertRequestLineEquals(request,
+               "PUT https://identity.blob.core.windows.net/container?restype=container HTTP/1.1");
+      assertNonPayloadHeadersEqual(request,
+               "x-ms-blob-public-access: blob\nx-ms-meta-foo: bar\nx-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, FalseIfContainerAlreadyExists.class);
+   }
+
+   public void testCreateRootContainer() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "createRootContainer", CreateContainerOptions[].class);
+
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of());
+
+      assertRequestLineEquals(request, "PUT https://identity.blob.core.windows.net/$root?restype=container HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, FalseIfContainerAlreadyExists.class);
+   }
+
+   public void testDeleteRootContainer() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "deleteRootContainer");
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of());
+
+      assertRequestLineEquals(request, "DELETE https://identity.blob.core.windows.net/$root?restype=container HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, TrueOnNotFoundOr404.class);
+   }
+
+   public void testCreateRootContainerOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "createRootContainer", CreateContainerOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(withPublicAccess(PublicAccess.BLOB).withMetadata(
+               ImmutableMultimap.of("foo", "bar"))));
+
+      assertRequestLineEquals(request, "PUT https://identity.blob.core.windows.net/$root?restype=container HTTP/1.1");
+      assertNonPayloadHeadersEqual(request,
+               "x-ms-blob-public-access: blob\nx-ms-meta-foo: bar\nx-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, FalseIfContainerAlreadyExists.class);
+   }
+
+   public void testListBlobs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "listBlobs", String.class, ListBlobsOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container"));
+
+      assertRequestLineEquals(request,
+               "GET https://identity.blob.core.windows.net/container?restype=container&comp=list HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ContainerNameEnumerationResultsHandler.class);
+      assertFallbackClassEquals(method, null);
+   }
+
+   public void testListRootBlobs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "listBlobs", ListBlobsOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of());
+
+      assertRequestLineEquals(request,
+               "GET https://identity.blob.core.windows.net/$root?restype=container&comp=list HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ContainerNameEnumerationResultsHandler.class);
+      assertFallbackClassEquals(method, null);
+   }
+
+   public void testContainerProperties() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "getContainerProperties", String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container"));
+
+      assertRequestLineEquals(request,
+               "HEAD https://identity.blob.core.windows.net/container?restype=container HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ParseContainerPropertiesFromHeaders.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, NullOnContainerNotFound.class);
+   }
+
+   public void testGetPublicAccessForContainer() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "getPublicAccessForContainer", String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container"));
+
+      assertRequestLineEquals(request,
+               "HEAD https://identity.blob.core.windows.net/container?restype=container&comp=acl HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ParsePublicAccessHeader.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, NullOnContainerNotFound.class);
+   }
+
+   public void testSetResourceMetadata() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "setResourceMetadata", String.class, Map.class);
+      GeneratedHttpRequest request = processor.createRequest(method,
+            ImmutableList.<Object> of("container", ImmutableMap.of("key", "value")));
+
+      assertRequestLineEquals(request,
+               "PUT https://identity.blob.core.windows.net/container?restype=container&comp=metadata HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "x-ms-meta-key: value\nx-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+   }
+
+   public void testGetBlob() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "getBlob", String.class, String.class, GetOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container", "blob"));
+
+      assertRequestLineEquals(request, "GET https://identity.blob.core.windows.net/container/blob HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ParseBlobFromHeadersAndHttpContent.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, NullOnKeyNotFound.class);
+   }
+
+   public void testSetBlobMetadata() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AzureBlobClient.class, "setBlobMetadata", String.class, String.class, Map.class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("container", "blob", ImmutableMap.of("key", "value")));
+
+      assertRequestLineEquals(request,
+               "PUT https://identity.blob.core.windows.net/container/blob?comp=metadata HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "x-ms-meta-key: value\nx-ms-version: 2009-09-19\n");
+      assertPayloadEquals(request, null, null, false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+   }
+
+   @Override
+   protected void checkFilters(HttpRequest request) {
+      assertEquals(request.getFilters().size(), 1);
+      assertEquals(request.getFilters().get(0).getClass(), SharedKeyLiteAuthentication.class);
+   }
+
+   @Override
+   public AzureBlobProviderMetadata createProviderMetadata() {
+      return new AzureBlobProviderMetadata();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/test/java/org/jclouds/azureblob/binders/BindAzureBlobMetadataToRequestTest.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/test/java/org/jclouds/azureblob/binders/BindAzureBlobMetadataToRequestTest.java b/providers/azureblob/src/test/java/org/jclouds/azureblob/binders/BindAzureBlobMetadataToRequestTest.java
index a933805..faec9bb 100644
--- a/providers/azureblob/src/test/java/org/jclouds/azureblob/binders/BindAzureBlobMetadataToRequestTest.java
+++ b/providers/azureblob/src/test/java/org/jclouds/azureblob/binders/BindAzureBlobMetadataToRequestTest.java
@@ -20,7 +20,7 @@ import static org.testng.Assert.assertEquals;
 
 import java.io.File;
 
-import org.jclouds.azureblob.AzureBlobAsyncClient;
+import org.jclouds.azureblob.AzureBlobClient;
 import org.jclouds.azureblob.AzureBlobProviderMetadata;
 import org.jclouds.azureblob.domain.AzureBlob;
 import org.jclouds.http.HttpRequest;
@@ -31,12 +31,8 @@ import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableMap;
 
-/**
- * Tests behavior of {@code BindAzureBlobMetadataToRequest}
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
 @Test(groups = "unit", testName = "BindAzureBlobMetadataToRequestTest")
-public class BindAzureBlobMetadataToRequestTest extends BaseAsyncClientTest<AzureBlobAsyncClient> {
+public class BindAzureBlobMetadataToRequestTest extends BaseAsyncClientTest<AzureBlobClient> {
 
    @Test
    public void testPassWithMinimumDetailsAndPayload64MB() {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/test/java/org/jclouds/azureblob/blobstore/AzureBlobRequestSignerTest.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/test/java/org/jclouds/azureblob/blobstore/AzureBlobRequestSignerTest.java b/providers/azureblob/src/test/java/org/jclouds/azureblob/blobstore/AzureBlobRequestSignerTest.java
index 240a028..3539e31 100644
--- a/providers/azureblob/src/test/java/org/jclouds/azureblob/blobstore/AzureBlobRequestSignerTest.java
+++ b/providers/azureblob/src/test/java/org/jclouds/azureblob/blobstore/AzureBlobRequestSignerTest.java
@@ -21,15 +21,15 @@ import static org.testng.Assert.assertEquals;
 import java.io.IOException;
 import java.util.Date;
 
-import org.jclouds.azureblob.AzureBlobAsyncClient;
+import org.jclouds.azureblob.AzureBlobClient;
 import org.jclouds.azureblob.AzureBlobProviderMetadata;
-import org.jclouds.azureblob.config.AzureBlobRestClientModule;
+import org.jclouds.azureblob.config.AzureBlobHttpApiModule;
 import org.jclouds.blobstore.BlobRequestSigner;
 import org.jclouds.blobstore.domain.Blob;
 import org.jclouds.blobstore.domain.Blob.Factory;
 import org.jclouds.date.TimeStamp;
 import org.jclouds.http.HttpRequest;
-import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.internal.BaseAsyncClientTest;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -42,7 +42,7 @@ import com.google.inject.Module;
  */
 // NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
 @Test(groups = "unit", testName = "AzureBlobRequestSignerTest")
-public class AzureBlobRequestSignerTest extends BaseAsyncClientTest<AzureBlobAsyncClient> {
+public class AzureBlobRequestSignerTest extends BaseAsyncClientTest<AzureBlobClient> {
 
    public AzureBlobRequestSignerTest() {
       // this is base64 decoded in the signer;
@@ -112,11 +112,11 @@ public class AzureBlobRequestSignerTest extends BaseAsyncClientTest<AzureBlobAsy
 
    @Override
    protected Module createModule() {
-      return new TestAzureBlobRestClientModule();
+      return new TestAzureBlobHttpApiModule();
    }
 
-      @ConfiguresRestClient
-   private static final class TestAzureBlobRestClientModule extends AzureBlobRestClientModule {
+      @ConfiguresHttpApi
+   private static final class TestAzureBlobHttpApiModule extends AzureBlobHttpApiModule {
       @Override
       protected void configure() {
          super.configure();

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/test/resources/test_error.xml
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/test/resources/test_error.xml b/providers/azureblob/src/test/resources/test_error.xml
new file mode 100644
index 0000000..6c12fac
--- /dev/null
+++ b/providers/azureblob/src/test/resources/test_error.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Error>
+	<Code>AuthenticationFailed</Code>
+	<Message>Server failed to authenticate the request. Make sure the value
+		of Authorization header is formed correctly including the signature.
+		RequestId:7859e884-e8b9-4ed0-aa62-ac6963b91bf6
+		Time:2009-09-02T23:32:36.7507749Z</Message>
+	<AuthenticationErrorDetail>The MAC signature found in the HTTP request
+		'XEv0NqP+zePZxlrHmxy2F6MiyoRD8LIJt1f/Swgzn1U=' is not the same as any
+		computed signature. Server used following string to sign: 'GET
+
+
+		Wed, 02 Sep 2009 23:32:34 GMT
+		/jclouds/?comp=list'.</AuthenticationErrorDetail>
+</Error>


[2/3] JCLOUDS-40 unasync azureblob; plus fold otherwise unused azure-common into it.

Posted by ad...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azure/storage/AzureStorageResponseException.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azure/storage/AzureStorageResponseException.java b/providers/azureblob/src/main/java/org/jclouds/azure/storage/AzureStorageResponseException.java
new file mode 100644
index 0000000..744de08
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azure/storage/AzureStorageResponseException.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage;
+
+import org.jclouds.azure.storage.domain.AzureStorageError;
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpResponseException;
+
+/**
+ * Encapsulates an Error from Azure Storage Services.
+ * 
+ * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingRESTError.html" />
+ * @see AzureStorageError
+ * @see org.jclouds.aws.handlers.ParseAzureStorageErrorFromXmlContent
+ */
+public class AzureStorageResponseException extends HttpResponseException {
+
+   private AzureStorageError error = new AzureStorageError();
+
+   public AzureStorageResponseException(HttpCommand command, HttpResponse response, AzureStorageError error) {
+      super(String.format("command %s failed with code %s, error: %s", command.toString(), response
+               .getStatusCode(), error.toString()), command, response);
+      this.setError(error);
+
+   }
+
+   public AzureStorageResponseException(HttpCommand command, HttpResponse response, AzureStorageError error,
+            Throwable cause) {
+      super(String.format("command %1$s failed with error: %2$s", command.toString(), error
+               .toString()), command, response, cause);
+      this.setError(error);
+
+   }
+
+   public AzureStorageResponseException(String message, HttpCommand command, HttpResponse response,
+            AzureStorageError error) {
+      super(message, command, response);
+      this.setError(error);
+
+   }
+
+   public AzureStorageResponseException(String message, HttpCommand command, HttpResponse response,
+            AzureStorageError error, Throwable cause) {
+      super(message, command, response, cause);
+      this.setError(error);
+
+   }
+
+   public void setError(AzureStorageError error) {
+      this.error = error;
+   }
+
+   public AzureStorageError getError() {
+      return error;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azure/storage/domain/AzureStorageError.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azure/storage/domain/AzureStorageError.java b/providers/azureblob/src/main/java/org/jclouds/azure/storage/domain/AzureStorageError.java
new file mode 100644
index 0000000..9843fb9
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azure/storage/domain/AzureStorageError.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.domain;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+/**
+ * When an Azure Storage request is in error, the client receives an error response.
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/dd573365.aspx" />
+ */
+public class AzureStorageError {
+   private String code;
+   private String message;
+   private String requestId;
+   private Map<String, String> details = Maps.newHashMap();
+   private String stringSigned;
+   private String signature;
+
+   @Override
+   public String toString() {
+      final StringBuilder sb = new StringBuilder();
+      sb.append("AzureError");
+      sb.append("{requestId='").append(requestId).append('\'');
+      if (code != null)
+         sb.append(", code='").append(code).append('\'');
+      if (message != null)
+         sb.append(", message='").append(message).append('\'');
+      if (stringSigned != null)
+         sb.append(", stringSigned='").append(stringSigned).append('\'');
+      if (getSignature() != null)
+         sb.append(", signature='").append(getSignature()).append('\'');
+      if (details.size() != 0)
+         sb.append(", context='").append(details.toString()).append('\'').append('}');
+      return sb.toString();
+   }
+
+   public void setCode(String code) {
+      this.code = code;
+   }
+
+   public String getCode() {
+      return code;
+   }
+
+   public void setMessage(String message) {
+      this.message = message;
+   }
+
+   public String getMessage() {
+      return message;
+   }
+
+   public void setRequestId(String requestId) {
+      this.requestId = requestId;
+   }
+
+   /**
+    * If a request is consistently failing and you have verified that the request is properly
+    * formulated, you may use this value to report the error to Microsoft. In your report, include
+    * the value of x-ms-request-id, the approximate time that the request was made, the storage
+    * service against which the request was made, and the type of operation that the request
+    * attempted
+    */
+   public String getRequestId() {
+      return requestId;
+   }
+
+   public void setStringSigned(String stringSigned) {
+      this.stringSigned = stringSigned;
+   }
+
+   /**
+    * @return what jclouds signed before sending the request.
+    */
+   public String getStringSigned() {
+      return stringSigned;
+   }
+
+   public void setDetails(Map<String, String> context) {
+      this.details = context;
+   }
+
+   /**
+    * @return additional details surrounding the error.
+    */
+   public Map<String, String> getDetails() {
+      return details;
+   }
+
+   public void setSignature(String signature) {
+      this.signature = signature;
+   }
+
+   public String getSignature() {
+      return signature;
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azure/storage/domain/BoundedSet.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azure/storage/domain/BoundedSet.java b/providers/azureblob/src/main/java/org/jclouds/azure/storage/domain/BoundedSet.java
new file mode 100644
index 0000000..8778ae6
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azure/storage/domain/BoundedSet.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.domain;
+
+import java.net.URI;
+import java.util.Set;
+
+public interface BoundedSet<T> extends Set<T> {
+   URI getUrl();
+
+   String getPrefix();
+
+   String getMarker();
+
+   int getMaxResults();
+
+   String getNextMarker();
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azure/storage/domain/internal/BoundedHashSet.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azure/storage/domain/internal/BoundedHashSet.java b/providers/azureblob/src/main/java/org/jclouds/azure/storage/domain/internal/BoundedHashSet.java
new file mode 100644
index 0000000..b9767ec
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azure/storage/domain/internal/BoundedHashSet.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.domain.internal;
+
+import java.net.URI;
+import java.util.HashSet;
+
+import org.jclouds.azure.storage.domain.BoundedSet;
+
+import com.google.common.collect.Iterables;
+
+public class BoundedHashSet<T> extends HashSet<T> implements BoundedSet<T> {
+
+   protected final URI url;
+   protected final String prefix;
+   protected final String marker;
+   protected final Integer maxResults;
+   protected final String nextMarker;
+
+   public BoundedHashSet(Iterable<T> contents, URI url, String prefix, String marker,
+            Integer maxResults, String nextMarker) {
+      Iterables.addAll(this, contents);
+      this.url = url;
+      this.prefix = prefix;
+      this.nextMarker = nextMarker;
+      this.maxResults = maxResults;
+      this.marker = marker;
+   }
+
+   public String getPrefix() {
+      return prefix;
+   }
+
+   public String getMarker() {
+      return marker;
+   }
+
+   public int getMaxResults() {
+      return maxResults;
+   }
+
+   public String getNextMarker() {
+      return nextMarker;
+   }
+
+   public URI getUrl() {
+      return url;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthentication.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthentication.java b/providers/azureblob/src/main/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthentication.java
new file mode 100644
index 0000000..8e56390
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthentication.java
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.filters;
+
+import static com.google.common.io.BaseEncoding.base64;
+import static com.google.common.io.ByteStreams.readBytes;
+import static org.jclouds.crypto.Macs.asByteProcessor;
+import static org.jclouds.util.Patterns.NEWLINE_PATTERN;
+import static org.jclouds.util.Strings2.toInputStream;
+
+import java.util.Collection;
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.jclouds.Constants;
+import org.jclouds.crypto.Crypto;
+import org.jclouds.date.TimeStamp;
+import org.jclouds.domain.Credentials;
+import org.jclouds.http.HttpException;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpRequestFilter;
+import org.jclouds.http.HttpUtils;
+import org.jclouds.http.internal.SignatureWire;
+import org.jclouds.logging.Logger;
+import org.jclouds.util.Strings2;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Strings;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.Sets;
+import com.google.common.io.ByteProcessor;
+import com.google.common.net.HttpHeaders;
+
+/**
+ * Signs the Azure Storage request.
+ * 
+ * @see <a href= "http://msdn.microsoft.com/en-us/library/dd179428.aspx" />
+ */
+@Singleton
+public class SharedKeyLiteAuthentication implements HttpRequestFilter {
+   private static final Collection<String> FIRST_HEADERS_TO_SIGN = ImmutableList.of(HttpHeaders.DATE);
+
+   private final SignatureWire signatureWire;
+   private final Supplier<Credentials> creds;
+   private final Provider<String> timeStampProvider;
+   private final Crypto crypto;
+   private final HttpUtils utils;
+
+   @Resource
+   @Named(Constants.LOGGER_SIGNATURE)
+   Logger signatureLog = Logger.NULL;
+
+   @Inject
+   public SharedKeyLiteAuthentication(SignatureWire signatureWire,
+         @org.jclouds.location.Provider Supplier<Credentials> creds, @TimeStamp Provider<String> timeStampProvider,
+         Crypto crypto, HttpUtils utils) {
+      this.crypto = crypto;
+      this.utils = utils;
+      this.signatureWire = signatureWire;
+      this.creds = creds;
+      this.timeStampProvider = timeStampProvider;
+   }
+
+   public HttpRequest filter(HttpRequest request) throws HttpException {
+      request = replaceDateHeader(request);
+      String signature = calculateSignature(createStringToSign(request));
+      request = replaceAuthorizationHeader(request, signature);
+      utils.logRequest(signatureLog, request, "<<");
+      return request;
+   }
+
+   HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) {
+      return request.toBuilder()
+            .replaceHeader(HttpHeaders.AUTHORIZATION, "SharedKeyLite " + creds.get().identity + ":" + signature)
+            .build();
+   }
+
+   HttpRequest replaceDateHeader(HttpRequest request) {
+      Builder<String, String> builder = ImmutableMap.builder();
+      String date = timeStampProvider.get();
+      builder.put(HttpHeaders.DATE, date);
+      request = request.toBuilder().replaceHeaders(Multimaps.forMap(builder.build())).build();
+      return request;
+   }
+
+   public String createStringToSign(HttpRequest request) {
+      utils.logRequest(signatureLog, request, ">>");
+      StringBuilder buffer = new StringBuilder();
+      // re-sign the request
+      appendMethod(request, buffer);
+      appendPayloadMetadata(request, buffer);
+      appendHttpHeaders(request, buffer);
+      appendCanonicalizedHeaders(request, buffer);
+      appendCanonicalizedResource(request, buffer);
+      if (signatureWire.enabled())
+         signatureWire.output(buffer.toString());
+      return buffer.toString();
+   }
+
+   private void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) {
+      buffer.append(
+            HttpUtils.nullToEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata()
+                  .getContentMD5())).append("\n");
+      buffer.append(
+            Strings.nullToEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata()
+                  .getContentType())).append("\n");
+   }
+
+   private String calculateSignature(String toSign) throws HttpException {
+      String signature = signString(toSign);
+      if (signatureWire.enabled())
+         signatureWire.input(Strings2.toInputStream(signature));
+      return signature;
+   }
+
+   public String signString(String toSign) {
+      try {
+         ByteProcessor<byte[]> hmacSHA256 = asByteProcessor(crypto.hmacSHA256(base64().decode(creds.get().credential)));
+         return base64().encode(readBytes(toInputStream(toSign), hmacSHA256));
+      } catch (Exception e) {
+         throw new HttpException("error signing request", e);
+      }
+   }
+
+   private void appendMethod(HttpRequest request, StringBuilder toSign) {
+      toSign.append(request.getMethod()).append("\n");
+   }
+
+   private void appendCanonicalizedHeaders(HttpRequest request, StringBuilder toSign) {
+      // TreeSet == Sort the headers alphabetically.
+      Set<String> headers = Sets.newTreeSet(request.getHeaders().keySet());
+      for (String header : headers) {
+         if (header.startsWith("x-ms-")) {
+            toSign.append(header.toLowerCase()).append(":");
+            for (String value : request.getHeaders().get(header)) {
+               toSign.append(NEWLINE_PATTERN.matcher(value).replaceAll("")).append(",");
+            }
+            toSign.deleteCharAt(toSign.lastIndexOf(","));
+            toSign.append("\n");
+         }
+      }
+   }
+
+   private void appendHttpHeaders(HttpRequest request, StringBuilder toSign) {
+      for (String header : FIRST_HEADERS_TO_SIGN)
+         toSign.append(HttpUtils.nullToEmpty(request.getHeaders().get(header))).append("\n");
+   }
+
+   @VisibleForTesting
+   void appendCanonicalizedResource(HttpRequest request, StringBuilder toSign) {
+      // 1. Beginning with an empty string (""), append a forward slash (/), followed by the name of
+      // the identity that owns the resource being accessed.
+      toSign.append("/").append(creds.get().identity);
+      appendUriPath(request, toSign);
+   }
+
+   @VisibleForTesting
+   void appendUriPath(HttpRequest request, StringBuilder toSign) {
+      // 2. Append the resource's encoded URI path
+      toSign.append(request.getEndpoint().getRawPath());
+
+      // If the request URI addresses a component of the
+      // resource, append the appropriate query string. The query string should include the question
+      // mark and the comp parameter (for example, ?comp=metadata). No other parameters should be
+      // included on the query string.
+      if (request.getEndpoint().getQuery() != null) {
+         StringBuilder paramsToSign = new StringBuilder("?");
+
+         String[] params = request.getEndpoint().getQuery().split("&");
+         for (String param : params) {
+            String[] paramNameAndValue = param.split("=");
+
+            if ("comp".equals(paramNameAndValue[0])) {
+               paramsToSign.append(param);
+            }
+         }
+
+         if (paramsToSign.length() > 1) {
+            toSign.append(paramsToSign);
+         }
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azure/storage/handlers/AzureStorageClientErrorRetryHandler.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azure/storage/handlers/AzureStorageClientErrorRetryHandler.java b/providers/azureblob/src/main/java/org/jclouds/azure/storage/handlers/AzureStorageClientErrorRetryHandler.java
new file mode 100644
index 0000000..fadc772
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azure/storage/handlers/AzureStorageClientErrorRetryHandler.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.handlers;
+
+import java.io.ByteArrayInputStream;
+
+import javax.annotation.Resource;
+import javax.inject.Named;
+
+import org.jclouds.Constants;
+import org.jclouds.azure.storage.domain.AzureStorageError;
+import org.jclouds.azure.storage.util.AzureStorageUtils;
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpException;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpRetryHandler;
+import org.jclouds.http.HttpUtils;
+import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
+import org.jclouds.logging.Logger;
+
+import com.google.inject.Inject;
+
+/**
+ * Handles Retryable responses with error codes in the 4xx range
+ */
+public class AzureStorageClientErrorRetryHandler implements HttpRetryHandler {
+
+   @Inject(optional = true)
+   @Named(Constants.PROPERTY_MAX_RETRIES)
+   private int retryCountLimit = 5;
+
+   private final AzureStorageUtils utils;
+   private final BackoffLimitedRetryHandler backoffHandler;
+
+   @Resource
+   protected Logger logger = Logger.NULL;
+
+   @Inject
+   public AzureStorageClientErrorRetryHandler(BackoffLimitedRetryHandler backoffHandler,
+            AzureStorageUtils utils) {
+      this.backoffHandler = backoffHandler;
+      this.utils = utils;
+   }
+
+   public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
+      byte[] content = HttpUtils.closeClientButKeepContentStream(response);
+      command.incrementFailureCount();
+      if (!command.isReplayable()) {
+         logger.warn("Cannot retry after server error, command is not replayable: %1$s", command);
+         return false;
+      } else if (command.getFailureCount() > retryCountLimit) {
+         logger.warn(
+                  "Cannot retry after server error, command has exceeded retry limit %1$d: %2$s",
+                  retryCountLimit, command);
+         return false;
+      } else if (response.getStatusCode() == 409) {
+         // Content can be null in the case of HEAD requests
+         if (content != null) {
+            try {
+               AzureStorageError error = utils.parseAzureStorageErrorFromContent(command, response,
+                        new ByteArrayInputStream(content));
+               if ("ContainerBeingDeleted".equals(error.getCode())) {
+                  backoffHandler.imposeBackoffExponentialDelay(100L, 3, retryCountLimit, command
+                           .getFailureCount(), command.toString());
+                  return true;
+               }
+            } catch (HttpException e) {
+               logger.warn(e, "error parsing response: %s", new String(content));
+            }
+         }
+      }
+      return false;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azure/storage/handlers/ParseAzureStorageErrorFromXmlContent.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azure/storage/handlers/ParseAzureStorageErrorFromXmlContent.java b/providers/azureblob/src/main/java/org/jclouds/azure/storage/handlers/ParseAzureStorageErrorFromXmlContent.java
new file mode 100644
index 0000000..ece8176
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azure/storage/handlers/ParseAzureStorageErrorFromXmlContent.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.handlers;
+
+import static org.jclouds.http.HttpUtils.releasePayload;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+
+import org.jclouds.azure.storage.AzureStorageResponseException;
+import org.jclouds.azure.storage.domain.AzureStorageError;
+import org.jclouds.azure.storage.util.AzureStorageUtils;
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpResponseException;
+import org.jclouds.logging.Logger;
+import org.jclouds.rest.AuthorizationException;
+import org.jclouds.rest.ResourceNotFoundException;
+import org.jclouds.util.Strings2;
+
+/**
+ * This will parse and set an appropriate exception on the command object.
+ * 
+ * @see AzureStorageError
+ */
+public class ParseAzureStorageErrorFromXmlContent implements HttpErrorHandler {
+   @Resource
+   protected Logger logger = Logger.NULL;
+
+   private final AzureStorageUtils utils;
+
+   @Inject
+   public ParseAzureStorageErrorFromXmlContent(AzureStorageUtils utils) {
+      this.utils = utils;
+   }
+
+   public static final Pattern CONTAINER_PATH = Pattern.compile("^[/]?([^/]+)$");
+   public static final Pattern CONTAINER_KEY_PATH = Pattern.compile("^[/]?([^/]+)/(.*)$");
+
+   public void handleError(HttpCommand command, HttpResponse response) {
+      Exception exception = new HttpResponseException(command, response);
+      String message = null;
+      AzureStorageError error = null;
+      try {
+         if (response.getPayload() != null) {
+            String contentType = response.getPayload().getContentMetadata().getContentType();
+            if (contentType != null && (contentType.indexOf("xml") != -1 || contentType.indexOf("unknown") != -1)
+                     && !Long.valueOf(0).equals(response.getPayload().getContentMetadata().getContentLength())) {
+               try {
+                  error = utils.parseAzureStorageErrorFromContent(command, response, response.getPayload().getInput());
+                  if (error != null) {
+                     message = error.getMessage();
+                     exception = new AzureStorageResponseException(command, response, error);
+                  }
+               } catch (RuntimeException e) {
+                  try {
+                     message = Strings2.toStringAndClose(response.getPayload().openStream());
+                     exception = new HttpResponseException(command, response, message);
+                  } catch (IOException e1) {
+                  }
+               }
+            } else {
+               try {
+                  message = Strings2.toStringAndClose(response.getPayload().openStream());
+                  exception = new HttpResponseException(command, response, message);
+               } catch (IOException e) {
+               }
+            }
+         }
+         message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
+                  response.getStatusLine());
+         exception = refineException(command, response, exception, error, message);
+      } finally {
+         releasePayload(response);
+         command.setException(exception);
+      }
+   }
+
+   protected Exception refineException(HttpCommand command, HttpResponse response, Exception exception,
+            AzureStorageError error, String message) {
+      switch (response.getStatusCode()) {
+         case 401:
+            exception = new AuthorizationException(message, exception);
+            break;
+         case 404:
+            if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
+               exception = new ResourceNotFoundException(message, exception);
+            }
+            break;
+         case 411:
+            exception = new IllegalArgumentException(message);
+            break;
+      }
+      return exception;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azure/storage/options/CreateOptions.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azure/storage/options/CreateOptions.java b/providers/azureblob/src/main/java/org/jclouds/azure/storage/options/CreateOptions.java
new file mode 100644
index 0000000..20fd7f8
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azure/storage/options/CreateOptions.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.options;
+
+import java.util.Map.Entry;
+
+import org.jclouds.azure.storage.reference.AzureStorageHeaders;
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+import com.google.common.collect.Multimap;
+
+/**
+ * Contains common options supported in the REST API for the Create operation. <h2>
+ * Usage</h2> The recommended way to instantiate a CreateOptions object is to statically import
+ * CreateOptions.* and invoke a static creation method followed by an instance mutator (if
+ * needed):
+ * <p/>
+ * <code>
+ * import static CreateOptions.Builder.*
+ * import org.jclouds.azure.storage.queue.AzureQueueClient;
+ * <p/>
+ * AzureQueueClient connection = // get connection
+ * Multimap<String,String> metadata = // ...
+ * boolean createdWithPublicAcl = connection.createQueue("containerName", withMetadata(metadata));
+ * <code> *
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/dd179466.aspx" />
+ */
+public class CreateOptions extends BaseHttpRequestOptions {
+   public static final CreateOptions NONE = new CreateOptions();
+
+   /**
+    * A name-value pair to associate with the container as metadata.
+    * 
+    * Note that these are stored at the server under the prefix: x-ms-meta-
+    */
+   public CreateOptions withMetadata(Multimap<String, String> metadata) {
+      for (Entry<String, String> entry : metadata.entries()) {
+         if (entry.getKey().startsWith(AzureStorageHeaders.USER_METADATA_PREFIX))
+            headers.put(entry.getKey(), entry.getValue());
+         else
+            headers
+                     .put(AzureStorageHeaders.USER_METADATA_PREFIX + entry.getKey(), entry
+                              .getValue());
+      }
+      return this;
+   }
+
+   public static class Builder {
+
+      /**
+       * @see CreateOptions#withMetadata(Multimap<String, String>)
+       */
+      public static CreateOptions withMetadata(Multimap<String, String> metadata) {
+         CreateOptions options = new CreateOptions();
+         return options.withMetadata(metadata);
+      }
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azure/storage/options/ListOptions.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azure/storage/options/ListOptions.java b/providers/azureblob/src/main/java/org/jclouds/azure/storage/options/ListOptions.java
new file mode 100644
index 0000000..fba5f39
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azure/storage/options/ListOptions.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.options;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Options used to control paginated results (aka list commands).
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/dd179466.aspx" />
+ */
+public class ListOptions extends BaseHttpRequestOptions {
+   public static final ListOptions NONE = new ListOptions();
+
+   /**
+    * Include this parameter to specify that the container's metadata be returned as part of the
+    * response body.
+    * 
+    * Note that metadata requested with this parameter must be stored in accordance with the naming
+    * restrictions imposed by the 2009-09-19 version of the Blob service. Beginning with this
+    * version, all metadata names must adhere to the naming conventions for C# identifiers.
+    */
+   public ListOptions includeMetadata() {
+      this.queryParameters.replaceValues("include", ImmutableSet.of("metadata"));
+      return this;
+   }
+
+   public boolean getIncludeMetadata() {
+      return getFirstQueryOrNull("include").equals("metadata");
+   }
+
+   /**
+    * Filters the results to return only objects whose name begins with the specified prefix.
+    */
+   public ListOptions prefix(String prefix) {
+      this.queryParameters.put("prefix", checkNotNull(prefix, "prefix"));
+      return this;
+   }
+
+   public String getPrefix() {
+      return getFirstQueryOrNull("prefix");
+   }
+
+   /**
+    * A string value that identifies the portion of the list to be returned with the next list
+    * operation. The operation returns a marker value within the response body if the list returned
+    * was not complete. The marker value may then be used in a subsequent call to request the next
+    * set of list items.
+    * <p/>
+    * The marker value is opaque to the client.
+    */
+   public ListOptions marker(String marker) {
+      this.queryParameters.put("marker", checkNotNull(marker, "marker"));
+      return this;
+   }
+
+   public String getMarker() {
+      return getFirstQueryOrNull("marker");
+   }
+
+   /**
+    * Specifies the maximum number of containers to return. If maxresults is not specified, the
+    * server will return up to 5,000 items. If the parameter is set to a value greater than 5,000,
+    * the server will return a Bad Request (400) error
+    */
+   public ListOptions maxResults(int maxresults) {
+      checkState(maxresults >= 0, "maxresults must be >= 0");
+      checkState(maxresults <= 10000, "maxresults must be <= 5000");
+      queryParameters.put("maxresults", Integer.toString(maxresults));
+      return this;
+   }
+
+   public Integer getMaxResults() {
+      String maxresults = getFirstQueryOrNull("maxresults");
+      return (maxresults != null) ? Integer.valueOf(maxresults) : null;
+   }
+
+   public static class Builder {
+      /**
+       * @see ListOptions#includeMetadata()
+       */
+      public static ListOptions includeMetadata() {
+         ListOptions options = new ListOptions();
+         return options.includeMetadata();
+      }
+
+      /**
+       * @see ListOptions#prefix(String)
+       */
+      public static ListOptions prefix(String prefix) {
+         ListOptions options = new ListOptions();
+         return options.prefix(prefix);
+      }
+
+      /**
+       * @see ListOptions#marker(String)
+       */
+      public static ListOptions marker(String marker) {
+         ListOptions options = new ListOptions();
+         return options.marker(marker);
+      }
+
+      /**
+       * @see ListOptions#maxResults(long)
+       */
+      public static ListOptions maxResults(int maxKeys) {
+         ListOptions options = new ListOptions();
+         return options.maxResults(maxKeys);
+      }
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azure/storage/reference/AzureStorageHeaders.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azure/storage/reference/AzureStorageHeaders.java b/providers/azureblob/src/main/java/org/jclouds/azure/storage/reference/AzureStorageHeaders.java
new file mode 100644
index 0000000..a51fa54
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azure/storage/reference/AzureStorageHeaders.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.reference;
+
+/**
+ * Additional headers specified by Azure Storage REST API.
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/dd179357.aspx" />
+ */
+public interface AzureStorageHeaders {
+
+   public static final String USER_METADATA_PREFIX = "x-ms-meta-";
+   public static final String REQUEST_ID = "x-ms-request-id";
+   public static final String VERSION = "x-ms-version";
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azure/storage/util/AzureStorageUtils.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azure/storage/util/AzureStorageUtils.java b/providers/azureblob/src/main/java/org/jclouds/azure/storage/util/AzureStorageUtils.java
new file mode 100644
index 0000000..bf62ff82a
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azure/storage/util/AzureStorageUtils.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.util;
+
+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.SharedKeyLiteAuthentication;
+import org.jclouds.azure.storage.reference.AzureStorageHeaders;
+import org.jclouds.azure.storage.xml.ErrorHandler;
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpException;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseSax;
+
+/**
+ * Encryption, Hashing, and IO Utilities needed to sign and verify Azure Storage requests and
+ * responses.
+ */
+public class AzureStorageUtils {
+
+   @Inject
+   SharedKeyLiteAuthentication signer;
+
+   @Inject
+   ParseSax.Factory factory;
+
+   @Inject
+   Provider<ErrorHandler> errorHandlerProvider;
+
+   public AzureStorageError parseAzureStorageErrorFromContent(HttpCommand command,
+            HttpResponse response, InputStream content) throws HttpException {
+      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.getCurrentRequest()));
+         error.setSignature(signer.signString(error.getStringSigned()));
+      }
+      return error;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azure/storage/xml/ErrorHandler.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azure/storage/xml/ErrorHandler.java b/providers/azureblob/src/main/java/org/jclouds/azure/storage/xml/ErrorHandler.java
new file mode 100644
index 0000000..9ea9bb1
--- /dev/null
+++ b/providers/azureblob/src/main/java/org/jclouds/azure/storage/xml/ErrorHandler.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.azure.storage.xml;
+
+import org.jclouds.azure.storage.domain.AzureStorageError;
+import org.jclouds.http.functions.ParseSax;
+
+/**
+ * Parses the error from the Amazon S3 REST API.
+ * 
+ * @see <a
+ *      href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingRESTError.html"
+ *      />
+ */
+public class ErrorHandler extends ParseSax.HandlerWithResult<AzureStorageError> {
+
+   private AzureStorageError error = new AzureStorageError();
+   private StringBuilder currentText = new StringBuilder();
+
+   public AzureStorageError getResult() {
+      return error;
+   }
+
+   public void endElement(String uri, String name, String qName) {
+
+      if (qName.equals("Code")) {
+         error.setCode(currentText.toString().trim());
+      } else if (qName.equals("Message")) {
+         error.setMessage(currentText.toString().trim());
+      } else if (!qName.equals("Error")) {
+         error.getDetails().put(qName, currentText.toString());
+      }
+      currentText = new StringBuilder();
+   }
+
+   public void characters(char ch[], int start, int length) {
+      currentText.append(ch, start, length);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobApiMetadata.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobApiMetadata.java b/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobApiMetadata.java
index c498f26..7798865 100644
--- a/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobApiMetadata.java
+++ b/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobApiMetadata.java
@@ -23,28 +23,15 @@ import java.net.URI;
 import java.util.Properties;
 
 import org.jclouds.azureblob.blobstore.config.AzureBlobStoreContextModule;
-import org.jclouds.azureblob.config.AzureBlobRestClientModule;
+import org.jclouds.azureblob.config.AzureBlobHttpApiModule;
 import org.jclouds.blobstore.BlobStoreContext;
-import org.jclouds.rest.internal.BaseRestApiMetadata;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
 
 import com.google.common.collect.ImmutableSet;
-import com.google.common.reflect.TypeToken;
 import com.google.inject.Module;
 
-/**
- * Implementation of {@link ApiMetadata} for Microsoft Azure Blob Service API
- */
-public class AzureBlobApiMetadata extends BaseRestApiMetadata {
+public class AzureBlobApiMetadata extends BaseHttpApiMetadata {
 
-   /**
-    * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(AzureBlobClient.class)} as
-    *             {@link AzureBlobAsyncClient} interface will be removed in jclouds 1.7.
-    */
-   @Deprecated
-   public static final TypeToken<org.jclouds.rest.RestContext<AzureBlobClient, AzureBlobAsyncClient>> CONTEXT_TOKEN = new TypeToken<org.jclouds.rest.RestContext<AzureBlobClient, AzureBlobAsyncClient>>() {
-      private static final long serialVersionUID = 1L;
-   };
-   
    private static Builder builder() {
       return new Builder();
    }
@@ -63,15 +50,14 @@ public class AzureBlobApiMetadata extends BaseRestApiMetadata {
    }
   
    public static Properties defaultProperties() {
-      Properties properties = BaseRestApiMetadata.defaultProperties();
+      Properties properties = BaseHttpApiMetadata.defaultProperties();
       properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "x-ms-meta-");
       return properties;
    }
    
-   public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
-      @SuppressWarnings("deprecation")
+   public static class Builder extends BaseHttpApiMetadata.Builder<AzureBlobClient, Builder> {
       protected Builder() {
-         super(AzureBlobClient.class, AzureBlobAsyncClient.class);
+         super(AzureBlobClient.class);
          id("azureblob")
          .name("Microsoft Azure Blob Service API")
          .identityName("Account Name")
@@ -81,7 +67,7 @@ public class AzureBlobApiMetadata extends BaseRestApiMetadata {
          .documentation(URI.create("http://msdn.microsoft.com/en-us/library/dd135733.aspx"))
          .defaultProperties(AzureBlobApiMetadata.defaultProperties())
          .view(typeToken(BlobStoreContext.class))
-         .defaultModules(ImmutableSet.<Class<? extends Module>>of(AzureBlobRestClientModule.class, AzureBlobStoreContextModule.class));
+         .defaultModules(ImmutableSet.<Class<? extends Module>>of(AzureBlobHttpApiModule.class, AzureBlobStoreContextModule.class));
       }
       
       @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobAsyncClient.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobAsyncClient.java b/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobAsyncClient.java
deleted file mode 100644
index f862689..0000000
--- a/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobAsyncClient.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azureblob;
-
-import static com.google.common.net.HttpHeaders.EXPECT;
-
-import java.util.List;
-import java.util.Map;
-
-import javax.inject.Named;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.HEAD;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.QueryParam;
-
-import org.jclouds.Fallbacks.TrueOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-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.azureblob.AzureBlobFallbacks.FalseIfContainerAlreadyExists;
-import org.jclouds.azureblob.binders.BindAzureBlobMetadataToRequest;
-import org.jclouds.azureblob.binders.BindAzureBlocksToRequest;
-import org.jclouds.azureblob.domain.BlobProperties;
-import org.jclouds.azureblob.domain.ContainerProperties;
-import org.jclouds.azureblob.domain.ListBlobBlocksResponse;
-import org.jclouds.azureblob.domain.ListBlobsResponse;
-import org.jclouds.azureblob.domain.PublicAccess;
-import org.jclouds.azureblob.functions.BlobName;
-import org.jclouds.azureblob.functions.ParseBlobFromHeadersAndHttpContent;
-import org.jclouds.azureblob.functions.ParseBlobPropertiesFromHeaders;
-import org.jclouds.azureblob.functions.ParseContainerPropertiesFromHeaders;
-import org.jclouds.azureblob.functions.ParsePublicAccessHeader;
-import org.jclouds.azureblob.options.CreateContainerOptions;
-import org.jclouds.azureblob.options.ListBlobsOptions;
-import org.jclouds.azureblob.predicates.validators.BlockIdValidator;
-import org.jclouds.azureblob.predicates.validators.ContainerNameValidator;
-import org.jclouds.azureblob.xml.AccountNameEnumerationResultsHandler;
-import org.jclouds.azureblob.xml.BlobBlocksResultsHandler;
-import org.jclouds.azureblob.xml.ContainerNameEnumerationResultsHandler;
-import org.jclouds.blobstore.BlobStoreFallbacks.FalseOnContainerNotFound;
-import org.jclouds.blobstore.BlobStoreFallbacks.FalseOnKeyNotFound;
-import org.jclouds.blobstore.BlobStoreFallbacks.NullOnContainerNotFound;
-import org.jclouds.blobstore.BlobStoreFallbacks.NullOnKeyNotFound;
-import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
-import org.jclouds.http.functions.ParseETagHeader;
-import org.jclouds.http.options.GetOptions;
-import org.jclouds.io.Payload;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Headers;
-import org.jclouds.rest.annotations.ParamParser;
-import org.jclouds.rest.annotations.ParamValidators;
-import org.jclouds.rest.annotations.QueryParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.ResponseParser;
-import org.jclouds.rest.annotations.SkipEncoding;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.inject.Provides;
-
-/**
- * Provides asynchronous access to Azure Blob via their REST API.
- * <p/>
- * All commands return a ListenableFuture of the result from Azure Blob. Any exceptions incurred
- * during processing will be backend in an {@link ExecutionException} as documented in
- * {@link ListenableFuture#get()}.
- * 
- * @see <a href="http://msdn.microsoft.com/en-us/library/dd135733.aspx" />
- * @see AzureBlobClient
- * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(AzureBlobClient.class)} as
- *             {@link AzureBlobAsyncClient} interface will be removed in jclouds 1.7.
- */
-@Deprecated
-@RequestFilters(SharedKeyLiteAuthentication.class)
-@Headers(keys = AzureStorageHeaders.VERSION, values = "2009-09-19")
-@SkipEncoding({ '/', '$' })
-@Path("/")
-public interface AzureBlobAsyncClient {
-   @Provides
-   org.jclouds.azureblob.domain.AzureBlob newBlob();
-
-   /**
-    * @see AzureBlobClient#listContainers
-    */
-   @Named("ListContainers")
-   @GET
-   @XMLResponseParser(AccountNameEnumerationResultsHandler.class)
-   @QueryParams(keys = "comp", values = "list")
-   ListenableFuture<? extends BoundedSet<ContainerProperties>> listContainers(ListOptions... listOptions);
-
-   /**
-    * @see AzureBlobClient#createContainer
-    */
-   @Named("CreateContainer")
-   @PUT
-   @Path("{container}")
-   @Fallback(FalseIfContainerAlreadyExists.class)
-   @QueryParams(keys = "restype", values = "container")
-   ListenableFuture<Boolean> createContainer(
-            @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
-            CreateContainerOptions... options);
-
-   /**
-    * @see AzureBlobClient#getPublicAccessForContainer
-    */
-   @Named("GetContainerACL")
-   @HEAD
-   @Path("{container}")
-   @QueryParams(keys = { "restype", "comp" }, values = { "container", "acl" })
-   @ResponseParser(ParsePublicAccessHeader.class)
-   @Fallback(NullOnContainerNotFound.class)
-   ListenableFuture<PublicAccess> getPublicAccessForContainer(
-            @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container);
-
-   /**
-    * @see AzureBlobClient#getContainerProperties
-    */
-   @Named("GetContainerProperties")
-   @HEAD
-   @Path("{container}")
-   @QueryParams(keys = "restype", values = "container")
-   @ResponseParser(ParseContainerPropertiesFromHeaders.class)
-   @Fallback(NullOnContainerNotFound.class)
-   ListenableFuture<ContainerProperties> getContainerProperties(
-            @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container);
-
-   /**
-    * @see AzureBlobClient#containerExists
-    */
-   @Named("GetContainerProperties")
-   @HEAD
-   @Path("{container}")
-   @QueryParams(keys = "restype", values = "container")
-   @Fallback(FalseOnContainerNotFound.class)
-   ListenableFuture<Boolean> containerExists(
-            @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container);
-
-   /**
-    * @see AzureBlobClient#setResourceMetadata
-    */
-   @Named("SetContainerMetadata")
-   @PUT
-   @Path("{container}")
-   @QueryParams(keys = { "restype", "comp" }, values = { "container", "metadata" })
-   ListenableFuture<Void> setResourceMetadata(
-            @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
-            @BinderParam(BindMapToHeadersWithPrefix.class) Map<String, String> metadata);
-
-   /**
-    * @see AzureBlobClient#deleteContainer
-    */
-   @Named("DeleteContainer")
-   @DELETE
-   @Path("{container}")
-   @Fallback(VoidOnNotFoundOr404.class)
-   @QueryParams(keys = "restype", values = "container")
-   ListenableFuture<Void> deleteContainer(
-            @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container);
-
-   /**
-    * @see AzureBlobClient#createRootContainer
-    */
-   @Named("CreateContainer")
-   @PUT
-   @Path("$root")
-   @Fallback(FalseIfContainerAlreadyExists.class)
-   @QueryParams(keys = "restype", values = "container")
-   ListenableFuture<Boolean> createRootContainer(CreateContainerOptions... options);
-
-   /**
-    * @see AzureBlobClient#deleteRootContainer
-    */
-   @Named("DeleteContainer")
-   @DELETE
-   @Path("$root")
-   @Fallback(TrueOnNotFoundOr404.class)
-   @QueryParams(keys = "restype", values = "container")
-   ListenableFuture<Void> deleteRootContainer();
-
-   /**
-    * @see AzureBlobClient#listBlobs(String, ListBlobsOptions[])
-    */
-   @Named("ListBlobs")
-   @GET
-   @XMLResponseParser(ContainerNameEnumerationResultsHandler.class)
-   @Path("{container}")
-   @QueryParams(keys = { "restype", "comp" }, values = { "container", "list" })
-   ListenableFuture<ListBlobsResponse> listBlobs(
-            @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
-            ListBlobsOptions... options);
-
-   /**
-    * @see AzureBlobClient#listBlobs(ListBlobsOptions[])
-    */
-   @Named("ListBlobs")
-   @GET
-   @XMLResponseParser(ContainerNameEnumerationResultsHandler.class)
-   @Path("$root")
-   @QueryParams(keys = { "restype", "comp" }, values = { "container", "list" })
-   ListenableFuture<ListBlobsResponse> listBlobs(ListBlobsOptions... options);
-
-   /**
-    * @see AzureBlobClient#putBlob
-    */
-   @Named("PutBlob")
-   @PUT
-   @Path("{container}/{name}")
-   @Headers(keys = EXPECT, values = "100-continue")
-   @ResponseParser(ParseETagHeader.class)
-   ListenableFuture<String> putBlob(
-            @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
-            @PathParam("name") @ParamParser(BlobName.class) @BinderParam(BindAzureBlobMetadataToRequest.class) org.jclouds.azureblob.domain.AzureBlob object);
-
-   /**
-    * @see AzureBlobClient#getBlob
-    */
-   @Named("GetBlob")
-   @GET
-   @ResponseParser(ParseBlobFromHeadersAndHttpContent.class)
-   @Fallback(NullOnKeyNotFound.class)
-   @Path("{container}/{name}")
-   ListenableFuture<org.jclouds.azureblob.domain.AzureBlob> getBlob(
-            @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
-            @PathParam("name") String name, GetOptions... options);
-
-   /**
-    * @see AzureBlobClient#getBlobProperties
-    */
-   @Named("GetBlobProperties")
-   @HEAD
-   @ResponseParser(ParseBlobPropertiesFromHeaders.class)
-   @Fallback(NullOnKeyNotFound.class)
-   @Path("{container}/{name}")
-   ListenableFuture<BlobProperties> getBlobProperties(
-            @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
-            @PathParam("name") String name);
-
-   /**
-    * @see AzureBlobClient#blobExists
-    *
-    */
-   @Named("GetBlobProperties")
-   @HEAD
-   @Fallback(FalseOnKeyNotFound.class)
-   @Path("{container}/{name}")
-   ListenableFuture<Boolean> blobExists(
-            @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
-            @PathParam("name") String name);
-
-   /**
-    * @see AzureBlobClient#setBlobMetadata
-    */
-   @Named("SetBlobMetadata")
-   @PUT
-   @Path("{container}/{name}")
-   @QueryParams(keys = { "comp" }, values = { "metadata" })
-   ListenableFuture<Void> setBlobMetadata(
-            @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
-            @PathParam("name") String name, @BinderParam(BindMapToHeadersWithPrefix.class) Map<String, String> metadata);
-
-   /**
-    * @see AzureBlobClient#deleteBlob
-    */
-   @Named("DeleteBlob")
-   @DELETE
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Path("{container}/{name}")
-   ListenableFuture<Void> deleteBlob(
-            @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
-            @PathParam("name") String name);
-
-
-   /**
-    * @see AzureBlobClient#putBlock
-    */
-   @Named("PutBlock")
-   @PUT
-   @Path("{container}/{name}")
-   @QueryParams(keys = { "comp" }, values = { "block" })
-   ListenableFuture<Void> putBlock(@PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
-                                   @PathParam("name") String name,
-                                   @QueryParam("blockid") @ParamValidators(BlockIdValidator.class) String blockId, Payload part);
-
-
-   /**
-    * @see AzureBlobClient#putBlockList
-    */
-   @Named("PutBlockList")
-   @PUT
-   @Path("{container}/{name}")
-   @ResponseParser(ParseETagHeader.class)
-   @QueryParams(keys = { "comp" }, values = { "blocklist" })
-   ListenableFuture<String> putBlockList(@PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
-                                         @PathParam("name") String name,
-                                         @BinderParam(BindAzureBlocksToRequest.class) List<String> blockIdList);
-
-   /**
-    * @see AzureBlobClient#getBlockList
-    */
-   @Named("GetBlockList")
-   @GET
-   @Path("{container}/{name}")
-   @XMLResponseParser(BlobBlocksResultsHandler.class)
-   @QueryParams(keys = { "comp" }, values = { "blocklist" })
-   ListenableFuture<ListBlobBlocksResponse> getBlockList(@PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
-                                                         @PathParam("name") String name);
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobClient.java
----------------------------------------------------------------------
diff --git a/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobClient.java b/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobClient.java
index 4d78ebb..790a0f4 100644
--- a/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobClient.java
+++ b/providers/azureblob/src/main/java/org/jclouds/azureblob/AzureBlobClient.java
@@ -16,32 +16,75 @@
  */
 package org.jclouds.azureblob;
 
+import static com.google.common.net.HttpHeaders.EXPECT;
+import static org.jclouds.Fallbacks.TrueOnNotFoundOr404;
+import static org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import static org.jclouds.azureblob.AzureBlobFallbacks.FalseIfContainerAlreadyExists;
+import static org.jclouds.blobstore.BlobStoreFallbacks.FalseOnContainerNotFound;
+import static org.jclouds.blobstore.BlobStoreFallbacks.FalseOnKeyNotFound;
+import static org.jclouds.blobstore.BlobStoreFallbacks.NullOnContainerNotFound;
+import static org.jclouds.blobstore.BlobStoreFallbacks.NullOnKeyNotFound;
+
+import java.io.Closeable;
 import java.util.List;
 import java.util.Map;
+
+import javax.inject.Named;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+
 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.azureblob.binders.BindAzureBlobMetadataToRequest;
+import org.jclouds.azureblob.binders.BindAzureBlocksToRequest;
 import org.jclouds.azureblob.domain.AzureBlob;
 import org.jclouds.azureblob.domain.BlobProperties;
 import org.jclouds.azureblob.domain.ContainerProperties;
 import org.jclouds.azureblob.domain.ListBlobBlocksResponse;
 import org.jclouds.azureblob.domain.ListBlobsResponse;
 import org.jclouds.azureblob.domain.PublicAccess;
+import org.jclouds.azureblob.functions.BlobName;
+import org.jclouds.azureblob.functions.ParseBlobFromHeadersAndHttpContent;
+import org.jclouds.azureblob.functions.ParseBlobPropertiesFromHeaders;
+import org.jclouds.azureblob.functions.ParseContainerPropertiesFromHeaders;
+import org.jclouds.azureblob.functions.ParsePublicAccessHeader;
 import org.jclouds.azureblob.options.CreateContainerOptions;
 import org.jclouds.azureblob.options.ListBlobsOptions;
+import org.jclouds.azureblob.predicates.validators.BlockIdValidator;
+import org.jclouds.azureblob.predicates.validators.ContainerNameValidator;
+import org.jclouds.azureblob.xml.AccountNameEnumerationResultsHandler;
+import org.jclouds.azureblob.xml.BlobBlocksResultsHandler;
+import org.jclouds.azureblob.xml.ContainerNameEnumerationResultsHandler;
+import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
+import org.jclouds.http.functions.ParseETagHeader;
 import org.jclouds.http.options.GetOptions;
+import org.jclouds.io.Payload;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.ParamParser;
+import org.jclouds.rest.annotations.ParamValidators;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.annotations.XMLResponseParser;
 
 import com.google.inject.Provides;
-import org.jclouds.io.Payload;
 
-/**
- * Provides access to Azure Blob via their REST API.
- * <p/>
- * All commands return a Future of the result from Azure Blob. Any exceptions incurred during
- * processing will be backend in an {@link ExecutionException} as documented in {@link Future#get()}.
- * 
- * @see <a href="http://msdn.microsoft.com/en-us/library/dd135733.aspx" />
- */
-public interface AzureBlobClient {
+/** Provides access to Azure Blob via their REST API.  */
+@RequestFilters(SharedKeyLiteAuthentication.class)
+@Headers(keys = AzureStorageHeaders.VERSION, values = "{jclouds.api-version}")
+@SkipEncoding({ '/', '$' })
+@Path("/")
+public interface AzureBlobClient extends Closeable {
    @Provides
    AzureBlob newBlob();
 
@@ -54,8 +97,13 @@ public interface AzureBlobClient {
     *           controls the number or type of results requested
     * @see ListOptions
     */
+   @Named("ListContainers")
+   @GET
+   @XMLResponseParser(AccountNameEnumerationResultsHandler.class)
+   @QueryParams(keys = "comp", values = "list")
    BoundedSet<ContainerProperties> listContainers(ListOptions... listOptions);
 
+
    /**
     * The Create Container operation creates a new container under the specified identity. If the
     * container with the same name already exists, the operation fails.
@@ -68,18 +116,38 @@ public interface AzureBlobClient {
     * @see CreateContainerOptions
     * 
     */
-   boolean createContainer(String container, CreateContainerOptions... options);
+   @Named("CreateContainer")
+   @PUT
+   @Path("{container}")
+   @Fallback(FalseIfContainerAlreadyExists.class)
+   @QueryParams(keys = "restype", values = "container")
+   boolean createContainer(@PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
+         CreateContainerOptions... options);
+
 
    /**
     * The Get Container Properties operation returns all user-defined metadata and system properties
     * for the specified container. The data returned does not include the container's list of blobs.
     */
-   ContainerProperties getContainerProperties(String container);
+   @Named("GetContainerProperties")
+   @HEAD
+   @Path("{container}")
+   @QueryParams(keys = "restype", values = "container")
+   @ResponseParser(ParseContainerPropertiesFromHeaders.class)
+   @Fallback(NullOnContainerNotFound.class)
+   ContainerProperties getContainerProperties(
+         @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container);
+
 
    /**
     * Issues a HEAD command to determine if the container exists or not.
     */
-   boolean containerExists(String container);
+   @Named("GetContainerProperties")
+   @HEAD
+   @Path("{container}")
+   @QueryParams(keys = "restype", values = "container")
+   @Fallback(FalseOnContainerNotFound.class)
+   boolean containerExists(@PathParam("container") @ParamValidators(ContainerNameValidator.class) String container);
 
    /**
     * The Set Container Metadata operation sets one or more user-defined name/value pairs for the
@@ -93,7 +161,14 @@ public interface AzureBlobClient {
     * <p/>
     * Calling Set Container Metadata updates the ETag for the container.
     */
-   void setResourceMetadata(String container, Map<String, String> metadata);
+   @Named("SetContainerMetadata")
+   @PUT
+   @Path("{container}")
+   @QueryParams(keys = { "restype", "comp" }, values = { "container", "metadata" })
+   void setResourceMetadata(
+         @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
+         @BinderParam(BindMapToHeadersWithPrefix.class) Map<String, String> metadata);
+
 
    /**
     * The Delete Container operation marks the specified container for deletion. The container and
@@ -108,7 +183,12 @@ public interface AzureBlobClient {
     * 404 (Not Found) while the container is being deleted.
     * 
     */
-   void deleteContainer(String container);
+   @Named("DeleteContainer")
+   @DELETE
+   @Path("{container}")
+   @Fallback(VoidOnNotFoundOr404.class)
+   @QueryParams(keys = "restype", values = "container")
+   void deleteContainer(@PathParam("container") @ParamValidators(ContainerNameValidator.class) String container);
 
    /**
     * The root container is a default container that may be inferred from a URL requesting a blob
@@ -121,15 +201,25 @@ public interface AzureBlobClient {
     * @see CreateContainerOptions
     * 
     */
+   @Named("CreateContainer")
+   @PUT
+   @Path("$root")
+   @Fallback(FalseIfContainerAlreadyExists.class)
+   @QueryParams(keys = "restype", values = "container")
    boolean createRootContainer(CreateContainerOptions... options);
 
    /**
-    * 
-    * 
-    * @param container
-    * @return whether data in the container may be accessed publicly and the level of access
+    * Returns whether data in the container may be accessed publicly and the level of access
     */
-   PublicAccess getPublicAccessForContainer(String container);
+   @Named("GetContainerACL")
+   @HEAD
+   @Path("{container}")
+   @QueryParams(keys = { "restype", "comp" }, values = { "container", "acl" })
+   @ResponseParser(ParsePublicAccessHeader.class)
+   @Fallback(NullOnContainerNotFound.class)
+   PublicAccess getPublicAccessForContainer(
+         @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container);
+
 
    /**
     * The Delete Container operation marks the specified container for deletion. The container and
@@ -142,9 +232,14 @@ public interface AzureBlobClient {
     * operations, including operations on any blobs under the container, will fail with status code
     * 404 (Not Found) while the container is being deleted.
     * 
-    * @see deleteContainer(String)
-    * @see createRootContainer(CreateContainerOptions)
+    * @see #deleteContainer(String)
+    * @see #createRootContainer(CreateContainerOptions...)
     */
+   @Named("DeleteContainer")
+   @DELETE
+   @Path("$root")
+   @Fallback(TrueOnNotFoundOr404.class)
+   @QueryParams(keys = "restype", values = "container")
    void deleteRootContainer();
 
    /**
@@ -182,8 +277,20 @@ public interface AzureBlobClient {
     * <p/>
     * Blobs are listed in alphabetical order in the response body.
     */
-   ListBlobsResponse listBlobs(String container, ListBlobsOptions... options);
+   @Named("ListBlobs")
+   @GET
+   @XMLResponseParser(ContainerNameEnumerationResultsHandler.class)
+   @Path("{container}")
+   @QueryParams(keys = { "restype", "comp" }, values = { "container", "list" })
+   ListBlobsResponse listBlobs(@PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
+         ListBlobsOptions... options);
 
+
+   @Named("ListBlobs")
+   @GET
+   @XMLResponseParser(ContainerNameEnumerationResultsHandler.class)
+   @Path("$root")
+   @QueryParams(keys = { "restype", "comp" }, values = { "container", "list" })
    ListBlobsResponse listBlobs(ListBlobsOptions... options);
 
    /**
@@ -201,57 +308,107 @@ public interface AzureBlobClient {
     * (Request Payload Too Large). The Blob service also returns additional information about the
     * error in the response, including the maximum blob size permitted in bytes.
     */
-   String putBlob(String container, AzureBlob object);
+   @Named("PutBlob")
+   @PUT
+   @Path("{container}/{name}")
+   @Headers(keys = EXPECT, values = "100-continue")
+   @ResponseParser(ParseETagHeader.class)
+   String putBlob(@PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
+         @PathParam("name") @ParamParser(BlobName.class) @BinderParam(BindAzureBlobMetadataToRequest.class)
+         AzureBlob object);
+
 
    /**
     * The Get Blob operation reads or downloads a blob from the system, including its metadata and
     * properties.
     */
-   AzureBlob getBlob(String container, String name, GetOptions... options);
+   @Named("GetBlob")
+   @GET
+   @ResponseParser(ParseBlobFromHeadersAndHttpContent.class)
+   @Fallback(NullOnKeyNotFound.class)
+   @Path("{container}/{name}")
+   AzureBlob getBlob(@PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
+         @PathParam("name") String name, GetOptions... options);
 
    /**
     *  The Put Block operation creates a block blob on Azure which can be later assembled into
     *  a single, large blob object with the Put Block List operation.
-    *
-    *  @see <a href="http://msdn.microsoft.com/en-us/library/windowsazure/dd135726.aspx">Put Blob</a>
     */
-   void putBlock(String container, String name, String blockId, Payload object);
+   @Named("PutBlock")
+   @PUT
+   @Path("{container}/{name}")
+   @QueryParams(keys = { "comp" }, values = { "block" })
+   void putBlock(@PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
+         @PathParam("name") String name,
+         @QueryParam("blockid") @ParamValidators(BlockIdValidator.class) String blockId, Payload part);
 
 
    /**
     *  The Put Block List assembles a list of blocks previously uploaded with Put Block into a single
     *  blob. Blocks are either already committed to a blob or uncommitted. The blocks ids passed here
     *  are searched for first in the uncommitted block list; then committed using the "latest" strategy.
-    *
-    *  @see <a href="http://msdn.microsoft.com/en-us/library/windowsazure/dd179467.aspx">Put Block List</a>
     */
-   String putBlockList(String container, String name, List<String> blockIdList);
+   @Named("PutBlockList")
+   @PUT
+   @Path("{container}/{name}")
+   @ResponseParser(ParseETagHeader.class)
+   @QueryParams(keys = { "comp" }, values = { "blocklist" })
+   String putBlockList(@PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
+         @PathParam("name") String name,
+         @BinderParam(BindAzureBlocksToRequest.class) List<String> blockIdList);
+
+   @Named("GetBlockList")
+   @GET
+   @Path("{container}/{name}")
+   @XMLResponseParser(BlobBlocksResultsHandler.class)
+   @QueryParams(keys = { "comp" }, values = { "blocklist" })
+   ListBlobBlocksResponse getBlockList(
+         @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
+         @PathParam("name") String name);
 
-   /**
-    * Get Block ID List for a blob
-    *
-    * @see <a href="http://msdn.microsoft.com/en-us/library/windowsazure/dd179400.aspx">Get Block List</a>
-    */
-   ListBlobBlocksResponse getBlockList(String container, String name);
 
    /**
     * The Get Blob Properties operation returns all user-defined metadata, standard HTTP properties,
     * and system properties for the blob. It does not return the content of the blob.
     */
-   BlobProperties getBlobProperties(String container, String name);
+   @Named("GetBlobProperties")
+   @HEAD
+   @ResponseParser(ParseBlobPropertiesFromHeaders.class)
+   @Fallback(NullOnKeyNotFound.class)
+   @Path("{container}/{name}")
+   BlobProperties getBlobProperties(
+         @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
+         @PathParam("name") String name);
 
-   void setBlobMetadata(String container, String name, Map<String, String> metadata);
+
+   @Named("SetBlobMetadata")
+   @PUT
+   @Path("{container}/{name}")
+   @QueryParams(keys = { "comp" }, values = { "metadata" })
+   void setBlobMetadata(
+         @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
+         @PathParam("name") String name, @BinderParam(BindMapToHeadersWithPrefix.class) Map<String, String> metadata);
 
    /**
     * The Delete Blob operation marks the specified blob for deletion. The blob is later deleted
     * during garbage collection.
     */
-   void deleteBlob(String container, String name);
-
+   @Named("DeleteBlob")
+   @DELETE
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Path("{container}/{name}")
+   void deleteBlob(
+         @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
+         @PathParam("name") String name);
    /**
-    * @throws ContainerNotFoundException
-    *            if the container is not present.
+    * @throws org.jclouds.blobstore.ContainerNotFoundException if the container is not present.
     */
-   boolean blobExists(String container, String name);
+   @Named("GetBlobProperties")
+   @HEAD
+   @Fallback(FalseOnKeyNotFound.class)
+   @Path("{container}/{name}")
+   boolean blobExists(
+         @PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
+         @PathParam("name") String name);
 
 }


[3/3] git commit: JCLOUDS-40 unasync azureblob; plus fold otherwise unused azure-common into it.

Posted by ad...@apache.org.
JCLOUDS-40 unasync azureblob; plus fold otherwise unused azure-common into it.


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/6843e0cb
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/6843e0cb
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/6843e0cb

Branch: refs/heads/1.8.x
Commit: 6843e0cbe8fc4ab85a8c15833e6dd916a37bae9d
Parents: e55f424
Author: Adrian Cole <ac...@twitter.com>
Authored: Fri Oct 3 17:35:37 2014 -0700
Committer: Adrian Cole <ad...@apache.org>
Committed: Fri Oct 3 22:12:27 2014 -0700

----------------------------------------------------------------------
 common/azure/README.txt                         |   6 -
 common/azure/pom.xml                            |  54 ---
 .../storage/AzureStorageResponseException.java  |  72 ----
 .../config/AzureStorageParserModule.java        |  31 --
 .../config/AzureStorageRestClientModule.java    |  98 ------
 .../azure/storage/domain/AzureStorageError.java | 114 -------
 .../azure/storage/domain/BoundedSet.java        |  33 --
 .../storage/domain/internal/BoundedHashSet.java |  64 ----
 .../filters/SharedKeyLiteAuthentication.java    | 207 ------------
 .../AzureStorageClientErrorRetryHandler.java    |  89 -----
 .../ParseAzureStorageErrorFromXmlContent.java   | 115 -------
 .../azure/storage/options/CreateOptions.java    |  74 -----
 .../azure/storage/options/ListOptions.java      | 131 --------
 .../storage/reference/AzureStorageHeaders.java  |  30 --
 .../azure/storage/util/AzureStorageUtils.java   |  59 ----
 .../jclouds/azure/storage/xml/ErrorHandler.java |  53 ---
 .../SharedKeyLiteAuthenticationTest.java        | 142 --------
 .../ParseAzureErrorFromXmlContentTest.java      | 116 -------
 .../storage/options/CreateOptionsTest.java      |  54 ---
 .../azure/storage/options/ListOptionsTest.java  |  71 ----
 .../azure/storage/xml/ErrorHandlerTest.java     |  47 ---
 common/azure/src/test/resources/log4j.xml       | 118 -------
 common/azure/src/test/resources/test_error.xml  |  15 -
 common/pom.xml                                  |   1 -
 providers/azureblob/pom.xml                     |   2 +-
 .../storage/AzureStorageResponseException.java  |  72 ++++
 .../azure/storage/domain/AzureStorageError.java | 114 +++++++
 .../azure/storage/domain/BoundedSet.java        |  33 ++
 .../storage/domain/internal/BoundedHashSet.java |  64 ++++
 .../filters/SharedKeyLiteAuthentication.java    | 207 ++++++++++++
 .../AzureStorageClientErrorRetryHandler.java    |  89 +++++
 .../ParseAzureStorageErrorFromXmlContent.java   | 115 +++++++
 .../azure/storage/options/CreateOptions.java    |  74 +++++
 .../azure/storage/options/ListOptions.java      | 131 ++++++++
 .../storage/reference/AzureStorageHeaders.java  |  30 ++
 .../azure/storage/util/AzureStorageUtils.java   |  59 ++++
 .../jclouds/azure/storage/xml/ErrorHandler.java |  53 +++
 .../jclouds/azureblob/AzureBlobApiMetadata.java |  28 +-
 .../jclouds/azureblob/AzureBlobAsyncClient.java | 328 -------------------
 .../org/jclouds/azureblob/AzureBlobClient.java  | 245 +++++++++++---
 .../blobstore/AzureAsyncBlobStore.java          | 307 -----------------
 .../blobstore/AzureBlobRequestSigner.java       |   8 +-
 .../config/AzureBlobStoreContextModule.java     |   7 +-
 .../config/AzureBlobHttpApiModule.java          |  88 +++++
 .../config/AzureBlobRestClientModule.java       |  48 ---
 .../SharedKeyLiteAuthenticationTest.java        | 142 ++++++++
 .../ParseAzureErrorFromXmlContentTest.java      | 116 +++++++
 .../storage/options/CreateOptionsTest.java      |  54 +++
 .../azure/storage/options/ListOptionsTest.java  |  71 ++++
 .../azure/storage/xml/ErrorHandlerTest.java     |  47 +++
 .../azureblob/AzureBlobAsyncClientTest.java     | 286 ----------------
 .../azureblob/AzureBlobClientLiveTest.java      |  15 +-
 .../jclouds/azureblob/AzureBlobClientTest.java  | 283 ++++++++++++++++
 .../BindAzureBlobMetadataToRequestTest.java     |   8 +-
 .../blobstore/AzureBlobRequestSignerTest.java   |  14 +-
 .../azureblob/src/test/resources/test_error.xml |  15 +
 56 files changed, 2087 insertions(+), 2860 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/README.txt
----------------------------------------------------------------------
diff --git a/common/azure/README.txt b/common/azure/README.txt
deleted file mode 100644
index 46ef3fc..0000000
--- a/common/azure/README.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# The jclouds provider for Microsoft Windows Azure (http://www.microsoft.com/windowsazure/).
-#
-# TODO: Implementation status.
-# TODO: Supported features.
-# TODO: Usage example.

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/pom.xml
----------------------------------------------------------------------
diff --git a/common/azure/pom.xml b/common/azure/pom.xml
deleted file mode 100644
index a4e5938..0000000
--- a/common/azure/pom.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.apache.jclouds</groupId>
-    <artifactId>jclouds-project</artifactId>
-    <version>1.8.1-SNAPSHOT</version>
-    <relativePath>../../project/pom.xml</relativePath>
-  </parent>
-  <groupId>org.apache.jclouds.common</groupId>
-  <artifactId>azure-common</artifactId>
-  <name>jclouds Azure Components Core</name>
-  <description>jclouds Core components to access Azure</description>
-  <packaging>bundle</packaging>
-
-  <properties>
-    <jclouds.osgi.export>org.jclouds.azure*;version="${project.version}"</jclouds.osgi.export>
-    <jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
-  </properties>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.jclouds</groupId>
-      <artifactId>jclouds-core</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds</groupId>
-      <artifactId>jclouds-core</artifactId>
-      <version>${project.version}</version>
-      <type>test-jar</type>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-
-</project>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/AzureStorageResponseException.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/AzureStorageResponseException.java b/common/azure/src/main/java/org/jclouds/azure/storage/AzureStorageResponseException.java
deleted file mode 100644
index 744de08..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/AzureStorageResponseException.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage;
-
-import org.jclouds.azure.storage.domain.AzureStorageError;
-import org.jclouds.http.HttpCommand;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.http.HttpResponseException;
-
-/**
- * Encapsulates an Error from Azure Storage Services.
- * 
- * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingRESTError.html" />
- * @see AzureStorageError
- * @see org.jclouds.aws.handlers.ParseAzureStorageErrorFromXmlContent
- */
-public class AzureStorageResponseException extends HttpResponseException {
-
-   private AzureStorageError error = new AzureStorageError();
-
-   public AzureStorageResponseException(HttpCommand command, HttpResponse response, AzureStorageError error) {
-      super(String.format("command %s failed with code %s, error: %s", command.toString(), response
-               .getStatusCode(), error.toString()), command, response);
-      this.setError(error);
-
-   }
-
-   public AzureStorageResponseException(HttpCommand command, HttpResponse response, AzureStorageError error,
-            Throwable cause) {
-      super(String.format("command %1$s failed with error: %2$s", command.toString(), error
-               .toString()), command, response, cause);
-      this.setError(error);
-
-   }
-
-   public AzureStorageResponseException(String message, HttpCommand command, HttpResponse response,
-            AzureStorageError error) {
-      super(message, command, response);
-      this.setError(error);
-
-   }
-
-   public AzureStorageResponseException(String message, HttpCommand command, HttpResponse response,
-            AzureStorageError error, Throwable cause) {
-      super(message, command, response, cause);
-      this.setError(error);
-
-   }
-
-   public void setError(AzureStorageError error) {
-      this.error = error;
-   }
-
-   public AzureStorageError getError() {
-      return error;
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/config/AzureStorageParserModule.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/config/AzureStorageParserModule.java b/common/azure/src/main/java/org/jclouds/azure/storage/config/AzureStorageParserModule.java
deleted file mode 100644
index a7bdd24..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/config/AzureStorageParserModule.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.config;
-
-import org.jclouds.json.config.GsonModule.DateAdapter;
-import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
-
-import com.google.inject.AbstractModule;
-
-public class AzureStorageParserModule extends AbstractModule {
-
-   @Override
-   protected void configure() {
-      bind(DateAdapter.class).to(Iso8601DateAdapter.class);
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/config/AzureStorageRestClientModule.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/config/AzureStorageRestClientModule.java b/common/azure/src/main/java/org/jclouds/azure/storage/config/AzureStorageRestClientModule.java
deleted file mode 100644
index 5f2e885..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/config/AzureStorageRestClientModule.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.config;
-
-import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
-
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-import javax.inject.Named;
-
-import org.jclouds.azure.storage.handlers.AzureStorageClientErrorRetryHandler;
-import org.jclouds.azure.storage.handlers.ParseAzureStorageErrorFromXmlContent;
-import org.jclouds.date.DateService;
-import org.jclouds.date.TimeStamp;
-import org.jclouds.http.HttpErrorHandler;
-import org.jclouds.http.HttpRetryHandler;
-import org.jclouds.http.annotation.ClientError;
-import org.jclouds.http.annotation.Redirection;
-import org.jclouds.http.annotation.ServerError;
-import org.jclouds.rest.ConfiguresRestClient;
-import org.jclouds.rest.config.RestClientModule;
-
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.google.common.reflect.TypeToken;
-import com.google.inject.Provides;
-
-/**
- * Configures the AzureStorage connection, including logging and http transport.
- */
-@ConfiguresRestClient
-public class AzureStorageRestClientModule<S, A> extends RestClientModule<S, A> {
-   protected AzureStorageRestClientModule() {
-
-   }
-
-   public AzureStorageRestClientModule(Map<Class<?>, Class<?>> delegate) {
-	      super(delegate);
-	   }
-   
-   public AzureStorageRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType) {
-      super(syncClientType, asyncClientType);
-   }
-
-   @Provides
-   @TimeStamp
-   protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
-      return cache.get();
-   }
-
-   /**
-    * borrowing concurrency code to ensure that caching takes place properly
-    */
-   @Provides
-   @TimeStamp
-   protected Supplier<String> provideTimeStampCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
-         final DateService dateService) {
-      return Suppliers.memoizeWithExpiration(new Supplier<String>() {
-         public String get() {
-            return dateService.rfc822DateFormat();
-         }
-      }, seconds, TimeUnit.SECONDS);
-   }
-
-   @Override
-   protected void bindErrorHandlers() {
-      bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseAzureStorageErrorFromXmlContent.class);
-      bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseAzureStorageErrorFromXmlContent.class);
-      bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseAzureStorageErrorFromXmlContent.class);
-   }
-
-   @Override
-   protected void bindRetryHandlers() {
-      bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(AzureStorageClientErrorRetryHandler.class);
-   }
-
-   @Override
-   protected void configure() {
-      install(new AzureStorageParserModule());
-      super.configure();
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/domain/AzureStorageError.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/domain/AzureStorageError.java b/common/azure/src/main/java/org/jclouds/azure/storage/domain/AzureStorageError.java
deleted file mode 100644
index 9843fb9..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/domain/AzureStorageError.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.domain;
-
-import java.util.Map;
-
-import com.google.common.collect.Maps;
-
-/**
- * When an Azure Storage request is in error, the client receives an error response.
- * 
- * @see <a href="http://msdn.microsoft.com/en-us/library/dd573365.aspx" />
- */
-public class AzureStorageError {
-   private String code;
-   private String message;
-   private String requestId;
-   private Map<String, String> details = Maps.newHashMap();
-   private String stringSigned;
-   private String signature;
-
-   @Override
-   public String toString() {
-      final StringBuilder sb = new StringBuilder();
-      sb.append("AzureError");
-      sb.append("{requestId='").append(requestId).append('\'');
-      if (code != null)
-         sb.append(", code='").append(code).append('\'');
-      if (message != null)
-         sb.append(", message='").append(message).append('\'');
-      if (stringSigned != null)
-         sb.append(", stringSigned='").append(stringSigned).append('\'');
-      if (getSignature() != null)
-         sb.append(", signature='").append(getSignature()).append('\'');
-      if (details.size() != 0)
-         sb.append(", context='").append(details.toString()).append('\'').append('}');
-      return sb.toString();
-   }
-
-   public void setCode(String code) {
-      this.code = code;
-   }
-
-   public String getCode() {
-      return code;
-   }
-
-   public void setMessage(String message) {
-      this.message = message;
-   }
-
-   public String getMessage() {
-      return message;
-   }
-
-   public void setRequestId(String requestId) {
-      this.requestId = requestId;
-   }
-
-   /**
-    * If a request is consistently failing and you have verified that the request is properly
-    * formulated, you may use this value to report the error to Microsoft. In your report, include
-    * the value of x-ms-request-id, the approximate time that the request was made, the storage
-    * service against which the request was made, and the type of operation that the request
-    * attempted
-    */
-   public String getRequestId() {
-      return requestId;
-   }
-
-   public void setStringSigned(String stringSigned) {
-      this.stringSigned = stringSigned;
-   }
-
-   /**
-    * @return what jclouds signed before sending the request.
-    */
-   public String getStringSigned() {
-      return stringSigned;
-   }
-
-   public void setDetails(Map<String, String> context) {
-      this.details = context;
-   }
-
-   /**
-    * @return additional details surrounding the error.
-    */
-   public Map<String, String> getDetails() {
-      return details;
-   }
-
-   public void setSignature(String signature) {
-      this.signature = signature;
-   }
-
-   public String getSignature() {
-      return signature;
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/domain/BoundedSet.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/domain/BoundedSet.java b/common/azure/src/main/java/org/jclouds/azure/storage/domain/BoundedSet.java
deleted file mode 100644
index 8778ae6..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/domain/BoundedSet.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.domain;
-
-import java.net.URI;
-import java.util.Set;
-
-public interface BoundedSet<T> extends Set<T> {
-   URI getUrl();
-
-   String getPrefix();
-
-   String getMarker();
-
-   int getMaxResults();
-
-   String getNextMarker();
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/domain/internal/BoundedHashSet.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/domain/internal/BoundedHashSet.java b/common/azure/src/main/java/org/jclouds/azure/storage/domain/internal/BoundedHashSet.java
deleted file mode 100644
index b9767ec..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/domain/internal/BoundedHashSet.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.domain.internal;
-
-import java.net.URI;
-import java.util.HashSet;
-
-import org.jclouds.azure.storage.domain.BoundedSet;
-
-import com.google.common.collect.Iterables;
-
-public class BoundedHashSet<T> extends HashSet<T> implements BoundedSet<T> {
-
-   protected final URI url;
-   protected final String prefix;
-   protected final String marker;
-   protected final Integer maxResults;
-   protected final String nextMarker;
-
-   public BoundedHashSet(Iterable<T> contents, URI url, String prefix, String marker,
-            Integer maxResults, String nextMarker) {
-      Iterables.addAll(this, contents);
-      this.url = url;
-      this.prefix = prefix;
-      this.nextMarker = nextMarker;
-      this.maxResults = maxResults;
-      this.marker = marker;
-   }
-
-   public String getPrefix() {
-      return prefix;
-   }
-
-   public String getMarker() {
-      return marker;
-   }
-
-   public int getMaxResults() {
-      return maxResults;
-   }
-
-   public String getNextMarker() {
-      return nextMarker;
-   }
-
-   public URI getUrl() {
-      return url;
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthentication.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthentication.java b/common/azure/src/main/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthentication.java
deleted file mode 100644
index 8e56390..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthentication.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.filters;
-
-import static com.google.common.io.BaseEncoding.base64;
-import static com.google.common.io.ByteStreams.readBytes;
-import static org.jclouds.crypto.Macs.asByteProcessor;
-import static org.jclouds.util.Patterns.NEWLINE_PATTERN;
-import static org.jclouds.util.Strings2.toInputStream;
-
-import java.util.Collection;
-import java.util.Set;
-
-import javax.annotation.Resource;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Provider;
-import javax.inject.Singleton;
-
-import org.jclouds.Constants;
-import org.jclouds.crypto.Crypto;
-import org.jclouds.date.TimeStamp;
-import org.jclouds.domain.Credentials;
-import org.jclouds.http.HttpException;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpRequestFilter;
-import org.jclouds.http.HttpUtils;
-import org.jclouds.http.internal.SignatureWire;
-import org.jclouds.logging.Logger;
-import org.jclouds.util.Strings2;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Strings;
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMap.Builder;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.Sets;
-import com.google.common.io.ByteProcessor;
-import com.google.common.net.HttpHeaders;
-
-/**
- * Signs the Azure Storage request.
- * 
- * @see <a href= "http://msdn.microsoft.com/en-us/library/dd179428.aspx" />
- */
-@Singleton
-public class SharedKeyLiteAuthentication implements HttpRequestFilter {
-   private static final Collection<String> FIRST_HEADERS_TO_SIGN = ImmutableList.of(HttpHeaders.DATE);
-
-   private final SignatureWire signatureWire;
-   private final Supplier<Credentials> creds;
-   private final Provider<String> timeStampProvider;
-   private final Crypto crypto;
-   private final HttpUtils utils;
-
-   @Resource
-   @Named(Constants.LOGGER_SIGNATURE)
-   Logger signatureLog = Logger.NULL;
-
-   @Inject
-   public SharedKeyLiteAuthentication(SignatureWire signatureWire,
-         @org.jclouds.location.Provider Supplier<Credentials> creds, @TimeStamp Provider<String> timeStampProvider,
-         Crypto crypto, HttpUtils utils) {
-      this.crypto = crypto;
-      this.utils = utils;
-      this.signatureWire = signatureWire;
-      this.creds = creds;
-      this.timeStampProvider = timeStampProvider;
-   }
-
-   public HttpRequest filter(HttpRequest request) throws HttpException {
-      request = replaceDateHeader(request);
-      String signature = calculateSignature(createStringToSign(request));
-      request = replaceAuthorizationHeader(request, signature);
-      utils.logRequest(signatureLog, request, "<<");
-      return request;
-   }
-
-   HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) {
-      return request.toBuilder()
-            .replaceHeader(HttpHeaders.AUTHORIZATION, "SharedKeyLite " + creds.get().identity + ":" + signature)
-            .build();
-   }
-
-   HttpRequest replaceDateHeader(HttpRequest request) {
-      Builder<String, String> builder = ImmutableMap.builder();
-      String date = timeStampProvider.get();
-      builder.put(HttpHeaders.DATE, date);
-      request = request.toBuilder().replaceHeaders(Multimaps.forMap(builder.build())).build();
-      return request;
-   }
-
-   public String createStringToSign(HttpRequest request) {
-      utils.logRequest(signatureLog, request, ">>");
-      StringBuilder buffer = new StringBuilder();
-      // re-sign the request
-      appendMethod(request, buffer);
-      appendPayloadMetadata(request, buffer);
-      appendHttpHeaders(request, buffer);
-      appendCanonicalizedHeaders(request, buffer);
-      appendCanonicalizedResource(request, buffer);
-      if (signatureWire.enabled())
-         signatureWire.output(buffer.toString());
-      return buffer.toString();
-   }
-
-   private void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) {
-      buffer.append(
-            HttpUtils.nullToEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata()
-                  .getContentMD5())).append("\n");
-      buffer.append(
-            Strings.nullToEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata()
-                  .getContentType())).append("\n");
-   }
-
-   private String calculateSignature(String toSign) throws HttpException {
-      String signature = signString(toSign);
-      if (signatureWire.enabled())
-         signatureWire.input(Strings2.toInputStream(signature));
-      return signature;
-   }
-
-   public String signString(String toSign) {
-      try {
-         ByteProcessor<byte[]> hmacSHA256 = asByteProcessor(crypto.hmacSHA256(base64().decode(creds.get().credential)));
-         return base64().encode(readBytes(toInputStream(toSign), hmacSHA256));
-      } catch (Exception e) {
-         throw new HttpException("error signing request", e);
-      }
-   }
-
-   private void appendMethod(HttpRequest request, StringBuilder toSign) {
-      toSign.append(request.getMethod()).append("\n");
-   }
-
-   private void appendCanonicalizedHeaders(HttpRequest request, StringBuilder toSign) {
-      // TreeSet == Sort the headers alphabetically.
-      Set<String> headers = Sets.newTreeSet(request.getHeaders().keySet());
-      for (String header : headers) {
-         if (header.startsWith("x-ms-")) {
-            toSign.append(header.toLowerCase()).append(":");
-            for (String value : request.getHeaders().get(header)) {
-               toSign.append(NEWLINE_PATTERN.matcher(value).replaceAll("")).append(",");
-            }
-            toSign.deleteCharAt(toSign.lastIndexOf(","));
-            toSign.append("\n");
-         }
-      }
-   }
-
-   private void appendHttpHeaders(HttpRequest request, StringBuilder toSign) {
-      for (String header : FIRST_HEADERS_TO_SIGN)
-         toSign.append(HttpUtils.nullToEmpty(request.getHeaders().get(header))).append("\n");
-   }
-
-   @VisibleForTesting
-   void appendCanonicalizedResource(HttpRequest request, StringBuilder toSign) {
-      // 1. Beginning with an empty string (""), append a forward slash (/), followed by the name of
-      // the identity that owns the resource being accessed.
-      toSign.append("/").append(creds.get().identity);
-      appendUriPath(request, toSign);
-   }
-
-   @VisibleForTesting
-   void appendUriPath(HttpRequest request, StringBuilder toSign) {
-      // 2. Append the resource's encoded URI path
-      toSign.append(request.getEndpoint().getRawPath());
-
-      // If the request URI addresses a component of the
-      // resource, append the appropriate query string. The query string should include the question
-      // mark and the comp parameter (for example, ?comp=metadata). No other parameters should be
-      // included on the query string.
-      if (request.getEndpoint().getQuery() != null) {
-         StringBuilder paramsToSign = new StringBuilder("?");
-
-         String[] params = request.getEndpoint().getQuery().split("&");
-         for (String param : params) {
-            String[] paramNameAndValue = param.split("=");
-
-            if ("comp".equals(paramNameAndValue[0])) {
-               paramsToSign.append(param);
-            }
-         }
-
-         if (paramsToSign.length() > 1) {
-            toSign.append(paramsToSign);
-         }
-      }
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/handlers/AzureStorageClientErrorRetryHandler.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/handlers/AzureStorageClientErrorRetryHandler.java b/common/azure/src/main/java/org/jclouds/azure/storage/handlers/AzureStorageClientErrorRetryHandler.java
deleted file mode 100644
index fadc772..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/handlers/AzureStorageClientErrorRetryHandler.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.handlers;
-
-import java.io.ByteArrayInputStream;
-
-import javax.annotation.Resource;
-import javax.inject.Named;
-
-import org.jclouds.Constants;
-import org.jclouds.azure.storage.domain.AzureStorageError;
-import org.jclouds.azure.storage.util.AzureStorageUtils;
-import org.jclouds.http.HttpCommand;
-import org.jclouds.http.HttpException;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.http.HttpRetryHandler;
-import org.jclouds.http.HttpUtils;
-import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
-import org.jclouds.logging.Logger;
-
-import com.google.inject.Inject;
-
-/**
- * Handles Retryable responses with error codes in the 4xx range
- */
-public class AzureStorageClientErrorRetryHandler implements HttpRetryHandler {
-
-   @Inject(optional = true)
-   @Named(Constants.PROPERTY_MAX_RETRIES)
-   private int retryCountLimit = 5;
-
-   private final AzureStorageUtils utils;
-   private final BackoffLimitedRetryHandler backoffHandler;
-
-   @Resource
-   protected Logger logger = Logger.NULL;
-
-   @Inject
-   public AzureStorageClientErrorRetryHandler(BackoffLimitedRetryHandler backoffHandler,
-            AzureStorageUtils utils) {
-      this.backoffHandler = backoffHandler;
-      this.utils = utils;
-   }
-
-   public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
-      byte[] content = HttpUtils.closeClientButKeepContentStream(response);
-      command.incrementFailureCount();
-      if (!command.isReplayable()) {
-         logger.warn("Cannot retry after server error, command is not replayable: %1$s", command);
-         return false;
-      } else if (command.getFailureCount() > retryCountLimit) {
-         logger.warn(
-                  "Cannot retry after server error, command has exceeded retry limit %1$d: %2$s",
-                  retryCountLimit, command);
-         return false;
-      } else if (response.getStatusCode() == 409) {
-         // Content can be null in the case of HEAD requests
-         if (content != null) {
-            try {
-               AzureStorageError error = utils.parseAzureStorageErrorFromContent(command, response,
-                        new ByteArrayInputStream(content));
-               if ("ContainerBeingDeleted".equals(error.getCode())) {
-                  backoffHandler.imposeBackoffExponentialDelay(100L, 3, retryCountLimit, command
-                           .getFailureCount(), command.toString());
-                  return true;
-               }
-            } catch (HttpException e) {
-               logger.warn(e, "error parsing response: %s", new String(content));
-            }
-         }
-      }
-      return false;
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/handlers/ParseAzureStorageErrorFromXmlContent.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/handlers/ParseAzureStorageErrorFromXmlContent.java b/common/azure/src/main/java/org/jclouds/azure/storage/handlers/ParseAzureStorageErrorFromXmlContent.java
deleted file mode 100644
index ece8176..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/handlers/ParseAzureStorageErrorFromXmlContent.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.handlers;
-
-import static org.jclouds.http.HttpUtils.releasePayload;
-
-import java.io.IOException;
-import java.util.regex.Pattern;
-
-import javax.annotation.Resource;
-import javax.inject.Inject;
-
-import org.jclouds.azure.storage.AzureStorageResponseException;
-import org.jclouds.azure.storage.domain.AzureStorageError;
-import org.jclouds.azure.storage.util.AzureStorageUtils;
-import org.jclouds.http.HttpCommand;
-import org.jclouds.http.HttpErrorHandler;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.http.HttpResponseException;
-import org.jclouds.logging.Logger;
-import org.jclouds.rest.AuthorizationException;
-import org.jclouds.rest.ResourceNotFoundException;
-import org.jclouds.util.Strings2;
-
-/**
- * This will parse and set an appropriate exception on the command object.
- * 
- * @see AzureStorageError
- */
-public class ParseAzureStorageErrorFromXmlContent implements HttpErrorHandler {
-   @Resource
-   protected Logger logger = Logger.NULL;
-
-   private final AzureStorageUtils utils;
-
-   @Inject
-   public ParseAzureStorageErrorFromXmlContent(AzureStorageUtils utils) {
-      this.utils = utils;
-   }
-
-   public static final Pattern CONTAINER_PATH = Pattern.compile("^[/]?([^/]+)$");
-   public static final Pattern CONTAINER_KEY_PATH = Pattern.compile("^[/]?([^/]+)/(.*)$");
-
-   public void handleError(HttpCommand command, HttpResponse response) {
-      Exception exception = new HttpResponseException(command, response);
-      String message = null;
-      AzureStorageError error = null;
-      try {
-         if (response.getPayload() != null) {
-            String contentType = response.getPayload().getContentMetadata().getContentType();
-            if (contentType != null && (contentType.indexOf("xml") != -1 || contentType.indexOf("unknown") != -1)
-                     && !Long.valueOf(0).equals(response.getPayload().getContentMetadata().getContentLength())) {
-               try {
-                  error = utils.parseAzureStorageErrorFromContent(command, response, response.getPayload().getInput());
-                  if (error != null) {
-                     message = error.getMessage();
-                     exception = new AzureStorageResponseException(command, response, error);
-                  }
-               } catch (RuntimeException e) {
-                  try {
-                     message = Strings2.toStringAndClose(response.getPayload().openStream());
-                     exception = new HttpResponseException(command, response, message);
-                  } catch (IOException e1) {
-                  }
-               }
-            } else {
-               try {
-                  message = Strings2.toStringAndClose(response.getPayload().openStream());
-                  exception = new HttpResponseException(command, response, message);
-               } catch (IOException e) {
-               }
-            }
-         }
-         message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
-                  response.getStatusLine());
-         exception = refineException(command, response, exception, error, message);
-      } finally {
-         releasePayload(response);
-         command.setException(exception);
-      }
-   }
-
-   protected Exception refineException(HttpCommand command, HttpResponse response, Exception exception,
-            AzureStorageError error, String message) {
-      switch (response.getStatusCode()) {
-         case 401:
-            exception = new AuthorizationException(message, exception);
-            break;
-         case 404:
-            if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
-               exception = new ResourceNotFoundException(message, exception);
-            }
-            break;
-         case 411:
-            exception = new IllegalArgumentException(message);
-            break;
-      }
-      return exception;
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/options/CreateOptions.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/options/CreateOptions.java b/common/azure/src/main/java/org/jclouds/azure/storage/options/CreateOptions.java
deleted file mode 100644
index 3fed43b..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/options/CreateOptions.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.options;
-
-import java.util.Map.Entry;
-
-import org.jclouds.azure.storage.reference.AzureStorageHeaders;
-import org.jclouds.http.options.BaseHttpRequestOptions;
-
-import com.google.common.collect.Multimap;
-
-/**
- * Contains common options supported in the REST API for the Create operation. <h2>
- * Usage</h2> The recommended way to instantiate a CreateOptions object is to statically import
- * CreateOptions.* and invoke a static creation method followed by an instance mutator (if
- * needed):
- * <p/>
- * <code>
- * import static org.jclouds.azure.storage.options.CreateOptions.Builder.*
- * import org.jclouds.azure.storage.queue.AzureQueueClient;
- * <p/>
- * AzureQueueClient connection = // get connection
- * Multimap<String,String> metadata = // ...
- * boolean createdWithPublicAcl = connection.createQueue("containerName", withMetadata(metadata));
- * <code> *
- * 
- * @see <a href="http://msdn.microsoft.com/en-us/library/dd179466.aspx" />
- */
-public class CreateOptions extends BaseHttpRequestOptions {
-   public static final CreateOptions NONE = new CreateOptions();
-
-   /**
-    * A name-value pair to associate with the container as metadata.
-    * 
-    * Note that these are stored at the server under the prefix: x-ms-meta-
-    */
-   public CreateOptions withMetadata(Multimap<String, String> metadata) {
-      for (Entry<String, String> entry : metadata.entries()) {
-         if (entry.getKey().startsWith(AzureStorageHeaders.USER_METADATA_PREFIX))
-            headers.put(entry.getKey(), entry.getValue());
-         else
-            headers
-                     .put(AzureStorageHeaders.USER_METADATA_PREFIX + entry.getKey(), entry
-                              .getValue());
-      }
-      return this;
-   }
-
-   public static class Builder {
-
-      /**
-       * @see CreateOptions#withMetadata(Multimap<String, String>)
-       */
-      public static CreateOptions withMetadata(Multimap<String, String> metadata) {
-         CreateOptions options = new CreateOptions();
-         return options.withMetadata(metadata);
-      }
-
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/options/ListOptions.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/options/ListOptions.java b/common/azure/src/main/java/org/jclouds/azure/storage/options/ListOptions.java
deleted file mode 100644
index fba5f39..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/options/ListOptions.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.options;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-import org.jclouds.http.options.BaseHttpRequestOptions;
-
-import com.google.common.collect.ImmutableSet;
-
-/**
- * Options used to control paginated results (aka list commands).
- * 
- * @see <a href="http://msdn.microsoft.com/en-us/library/dd179466.aspx" />
- */
-public class ListOptions extends BaseHttpRequestOptions {
-   public static final ListOptions NONE = new ListOptions();
-
-   /**
-    * Include this parameter to specify that the container's metadata be returned as part of the
-    * response body.
-    * 
-    * Note that metadata requested with this parameter must be stored in accordance with the naming
-    * restrictions imposed by the 2009-09-19 version of the Blob service. Beginning with this
-    * version, all metadata names must adhere to the naming conventions for C# identifiers.
-    */
-   public ListOptions includeMetadata() {
-      this.queryParameters.replaceValues("include", ImmutableSet.of("metadata"));
-      return this;
-   }
-
-   public boolean getIncludeMetadata() {
-      return getFirstQueryOrNull("include").equals("metadata");
-   }
-
-   /**
-    * Filters the results to return only objects whose name begins with the specified prefix.
-    */
-   public ListOptions prefix(String prefix) {
-      this.queryParameters.put("prefix", checkNotNull(prefix, "prefix"));
-      return this;
-   }
-
-   public String getPrefix() {
-      return getFirstQueryOrNull("prefix");
-   }
-
-   /**
-    * A string value that identifies the portion of the list to be returned with the next list
-    * operation. The operation returns a marker value within the response body if the list returned
-    * was not complete. The marker value may then be used in a subsequent call to request the next
-    * set of list items.
-    * <p/>
-    * The marker value is opaque to the client.
-    */
-   public ListOptions marker(String marker) {
-      this.queryParameters.put("marker", checkNotNull(marker, "marker"));
-      return this;
-   }
-
-   public String getMarker() {
-      return getFirstQueryOrNull("marker");
-   }
-
-   /**
-    * Specifies the maximum number of containers to return. If maxresults is not specified, the
-    * server will return up to 5,000 items. If the parameter is set to a value greater than 5,000,
-    * the server will return a Bad Request (400) error
-    */
-   public ListOptions maxResults(int maxresults) {
-      checkState(maxresults >= 0, "maxresults must be >= 0");
-      checkState(maxresults <= 10000, "maxresults must be <= 5000");
-      queryParameters.put("maxresults", Integer.toString(maxresults));
-      return this;
-   }
-
-   public Integer getMaxResults() {
-      String maxresults = getFirstQueryOrNull("maxresults");
-      return (maxresults != null) ? Integer.valueOf(maxresults) : null;
-   }
-
-   public static class Builder {
-      /**
-       * @see ListOptions#includeMetadata()
-       */
-      public static ListOptions includeMetadata() {
-         ListOptions options = new ListOptions();
-         return options.includeMetadata();
-      }
-
-      /**
-       * @see ListOptions#prefix(String)
-       */
-      public static ListOptions prefix(String prefix) {
-         ListOptions options = new ListOptions();
-         return options.prefix(prefix);
-      }
-
-      /**
-       * @see ListOptions#marker(String)
-       */
-      public static ListOptions marker(String marker) {
-         ListOptions options = new ListOptions();
-         return options.marker(marker);
-      }
-
-      /**
-       * @see ListOptions#maxResults(long)
-       */
-      public static ListOptions maxResults(int maxKeys) {
-         ListOptions options = new ListOptions();
-         return options.maxResults(maxKeys);
-      }
-
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/reference/AzureStorageHeaders.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/reference/AzureStorageHeaders.java b/common/azure/src/main/java/org/jclouds/azure/storage/reference/AzureStorageHeaders.java
deleted file mode 100644
index a51fa54..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/reference/AzureStorageHeaders.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.reference;
-
-/**
- * Additional headers specified by Azure Storage REST API.
- * 
- * @see <a href="http://msdn.microsoft.com/en-us/library/dd179357.aspx" />
- */
-public interface AzureStorageHeaders {
-
-   public static final String USER_METADATA_PREFIX = "x-ms-meta-";
-   public static final String REQUEST_ID = "x-ms-request-id";
-   public static final String VERSION = "x-ms-version";
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/util/AzureStorageUtils.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/util/AzureStorageUtils.java b/common/azure/src/main/java/org/jclouds/azure/storage/util/AzureStorageUtils.java
deleted file mode 100644
index bf62ff82a..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/util/AzureStorageUtils.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.util;
-
-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.SharedKeyLiteAuthentication;
-import org.jclouds.azure.storage.reference.AzureStorageHeaders;
-import org.jclouds.azure.storage.xml.ErrorHandler;
-import org.jclouds.http.HttpCommand;
-import org.jclouds.http.HttpException;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.http.functions.ParseSax;
-
-/**
- * Encryption, Hashing, and IO Utilities needed to sign and verify Azure Storage requests and
- * responses.
- */
-public class AzureStorageUtils {
-
-   @Inject
-   SharedKeyLiteAuthentication signer;
-
-   @Inject
-   ParseSax.Factory factory;
-
-   @Inject
-   Provider<ErrorHandler> errorHandlerProvider;
-
-   public AzureStorageError parseAzureStorageErrorFromContent(HttpCommand command,
-            HttpResponse response, InputStream content) throws HttpException {
-      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.getCurrentRequest()));
-         error.setSignature(signer.signString(error.getStringSigned()));
-      }
-      return error;
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/main/java/org/jclouds/azure/storage/xml/ErrorHandler.java
----------------------------------------------------------------------
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/xml/ErrorHandler.java b/common/azure/src/main/java/org/jclouds/azure/storage/xml/ErrorHandler.java
deleted file mode 100644
index 9ea9bb1..0000000
--- a/common/azure/src/main/java/org/jclouds/azure/storage/xml/ErrorHandler.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.xml;
-
-import org.jclouds.azure.storage.domain.AzureStorageError;
-import org.jclouds.http.functions.ParseSax;
-
-/**
- * Parses the error from the Amazon S3 REST API.
- * 
- * @see <a
- *      href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingRESTError.html"
- *      />
- */
-public class ErrorHandler extends ParseSax.HandlerWithResult<AzureStorageError> {
-
-   private AzureStorageError error = new AzureStorageError();
-   private StringBuilder currentText = new StringBuilder();
-
-   public AzureStorageError getResult() {
-      return error;
-   }
-
-   public void endElement(String uri, String name, String qName) {
-
-      if (qName.equals("Code")) {
-         error.setCode(currentText.toString().trim());
-      } else if (qName.equals("Message")) {
-         error.setMessage(currentText.toString().trim());
-      } else if (!qName.equals("Error")) {
-         error.getDetails().put(qName, currentText.toString());
-      }
-      currentText = new StringBuilder();
-   }
-
-   public void characters(char ch[], int start, int length) {
-      currentText.append(ch, start, length);
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/test/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthenticationTest.java
----------------------------------------------------------------------
diff --git a/common/azure/src/test/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthenticationTest.java b/common/azure/src/test/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthenticationTest.java
deleted file mode 100644
index 5bea836..0000000
--- a/common/azure/src/test/java/org/jclouds/azure/storage/filters/SharedKeyLiteAuthenticationTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.filters;
-
-import static org.jclouds.reflect.Reflection2.typeToken;
-import static org.testng.Assert.assertEquals;
-
-import java.io.IOException;
-import java.net.URI;
-
-import javax.ws.rs.HttpMethod;
-
-import org.jclouds.ContextBuilder;
-import org.jclouds.azure.storage.config.AzureStorageRestClientModule;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.IntegrationTestAsyncClient;
-import org.jclouds.http.IntegrationTestClient;
-import org.jclouds.logging.config.NullLoggingModule;
-import org.jclouds.rest.AnonymousRestApiMetadata;
-import org.jclouds.rest.internal.BaseRestApiTest.MockModule;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.net.HttpHeaders;
-import com.google.inject.Injector;
-import com.google.inject.Module;
-
-@Test(groups = "unit")
-public class SharedKeyLiteAuthenticationTest {
-
-   private static final String ACCOUNT = "foo";
-   private Injector injector;
-   private SharedKeyLiteAuthentication filter;
-
-   @DataProvider(parallel = true)
-   public Object[][] dataProvider() {
-      return new Object[][] {
-            { HttpRequest.builder().method(HttpMethod.PUT).endpoint("http://" + ACCOUNT
-                  + ".blob.core.windows.net/movies/MOV1.avi?comp=block&blockid=BlockId1&timeout=60").build() },
-            { HttpRequest.builder().method(HttpMethod.PUT).endpoint("http://" + ACCOUNT
-                  + ".blob.core.windows.net/movies/MOV1.avi?comp=blocklist&timeout=120").build() },
-            { HttpRequest.builder().method(HttpMethod.GET).endpoint("http://" + ACCOUNT + ".blob.core.windows.net/movies/MOV1.avi").build() } };
-   }
-
-   /**
-    * NOTE this test is dependent on how frequently the timestamp updates. At
-    * the time of writing, this was once per second. If this timestamp update
-    * interval is increased, it could make this test appear to hang for a long
-    * time.
-    */
-   @Test(threadPoolSize = 3, dataProvider = "dataProvider", timeOut = 3000)
-   void testIdempotent(HttpRequest request) {
-      request = filter.filter(request);
-      String signature = request.getFirstHeaderOrNull(HttpHeaders.AUTHORIZATION);
-      String date = request.getFirstHeaderOrNull(HttpHeaders.DATE);
-      int iterations = 1;
-      while (request.getFirstHeaderOrNull(HttpHeaders.DATE).equals(date)) {
-         date = request.getFirstHeaderOrNull(HttpHeaders.DATE);
-         iterations++;
-         assertEquals(signature, request.getFirstHeaderOrNull(HttpHeaders.AUTHORIZATION));
-         request = filter.filter(request);
-      }
-      System.out.printf("%s: %d iterations before the timestamp updated %n", Thread.currentThread().getName(),
-            iterations);
-   }
-
-   @Test
-   void testAclQueryStringRoot() {
-      URI host = URI.create("http://" + ACCOUNT + ".blob.core.windows.net/?comp=list");
-      HttpRequest request = HttpRequest.builder().method(HttpMethod.GET).endpoint(host).build();
-      StringBuilder builder = new StringBuilder();
-      filter.appendUriPath(request, builder);
-      assertEquals(builder.toString(), "/?comp=list");
-   }
-
-   @Test
-   void testAclQueryStringResTypeNotSignificant() {
-      URI host = URI.create("http://" + ACCOUNT + ".blob.core.windows.net/mycontainer?restype=container");
-      HttpRequest request = HttpRequest.builder().method(HttpMethod.GET).endpoint(host).build();
-      StringBuilder builder = new StringBuilder();
-      filter.appendUriPath(request, builder);
-      assertEquals(builder.toString(), "/mycontainer");
-   }
-
-   @Test
-   void testAclQueryStringComp() {
-      URI host = URI.create("http://" + ACCOUNT + ".blob.core.windows.net/mycontainer?comp=list");
-      HttpRequest request = HttpRequest.builder().method(HttpMethod.GET).endpoint(host).build();
-      StringBuilder builder = new StringBuilder();
-      filter.appendUriPath(request, builder);
-      assertEquals(builder.toString(), "/mycontainer?comp=list");
-   }
-
-   @Test
-   void testAclQueryStringRelativeWithExtraJunk() {
-      URI host = URI.create("http://" + ACCOUNT
-            + ".blob.core.windows.net/mycontainer?comp=list&marker=marker&maxresults=1&prefix=prefix");
-      HttpRequest request = HttpRequest.builder().method(HttpMethod.GET).endpoint(host).build();
-      StringBuilder builder = new StringBuilder();
-      filter.appendUriPath(request, builder);
-      assertEquals(builder.toString(), "/mycontainer?comp=list");
-   }
-
-   /**
-    * before class, as we need to ensure that the filter is threadsafe.
-    * 
-    * @throws IOException
-    * 
-    */
-   @BeforeClass
-   protected void createFilter() throws IOException {
-      injector = ContextBuilder
-            .newBuilder(
-                  AnonymousRestApiMetadata
-                        .forClientMappedToAsyncClient(IntegrationTestClient.class, IntegrationTestAsyncClient.class)
-                        .toBuilder().build())
-            .endpoint("https://${jclouds.identity}.blob.core.windows.net")
-            .credentials(ACCOUNT, "credential")
-            .modules(
-                  ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule(),
-                        new AzureStorageRestClientModule<IntegrationTestClient, IntegrationTestAsyncClient>(
-                              typeToken(IntegrationTestClient.class), typeToken(IntegrationTestAsyncClient.class))))
-            .buildInjector();
-      filter = injector.getInstance(SharedKeyLiteAuthentication.class);
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/test/java/org/jclouds/azure/storage/handlers/ParseAzureErrorFromXmlContentTest.java
----------------------------------------------------------------------
diff --git a/common/azure/src/test/java/org/jclouds/azure/storage/handlers/ParseAzureErrorFromXmlContentTest.java b/common/azure/src/test/java/org/jclouds/azure/storage/handlers/ParseAzureErrorFromXmlContentTest.java
deleted file mode 100644
index 5cfbffe..0000000
--- a/common/azure/src/test/java/org/jclouds/azure/storage/handlers/ParseAzureErrorFromXmlContentTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.handlers;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.reportMatcher;
-import static org.easymock.EasyMock.verify;
-
-import java.net.URI;
-
-import org.easymock.IArgumentMatcher;
-import org.jclouds.azure.storage.AzureStorageResponseException;
-import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
-import org.jclouds.http.HttpCommand;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.http.functions.config.SaxParserModule;
-import org.testng.annotations.Test;
-
-import com.google.inject.AbstractModule;
-import com.google.inject.Guice;
-
-@Test(groups = { "unit" })
-public class ParseAzureErrorFromXmlContentTest {
-
-   @Test
-   public void test411WithTextHtmlIllegalArgumentException() {
-      assertCodeMakes("PUT",
-            URI.create("https://jclouds.blob.core.windows.net/adriancole-azureblob-413790770?restype=container"), 411,
-            "Length Required", "text/html; charset=us-ascii", "<HTML><HEAD><TITLE>Length Required</TITLE>\r\n",
-            IllegalArgumentException.class);
-   }
-
-   @Test
-   public void test304WithNoContentIllegalArgumentException() {
-      assertCodeMakes("GET", URI.create("https://jclouds.blob.core.windows.net/adriancole-blobstore0/apples"), 411,
-            "HTTP/1.1 304 The condition specified using HTTP conditional header(s) is not met.", "application/unknown",
-            "", IllegalArgumentException.class);
-   }
-
-   
-   @Test
-   public void test412WithTextHtmlHttpResponseException() {
-      assertCodeMakes(
-            "GET",
-            URI.create("https://jclouds.blob.core.windows.net/adriancole-blobstore2?restype=container&comp=list&prefix=apps/apps/apps/&include=metadata"),
-            412,
-            "HTTP/1.1 412 The condition specified using HTTP conditional header(s) is not met.",
-            "application/xml",
-            "<?xml version=\"1.0\" encoding=\"utf-8\"?><Error><Code>ConditionNotMet</Code><Message>The condition specified using HTTP conditional header(s) is not met.\nRequestId:921efcad-84bc-4e0a-863d-24810d1096e1\nTime:2010-11-04T15:03:07.8694513Z</Message></Error>",
-            AzureStorageResponseException.class);
-   }
-
-   private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
-         String content, Class<? extends Exception> expected) {
-
-      ParseAzureStorageErrorFromXmlContent function = Guice.createInjector(new SaxParserModule(), new AbstractModule() {
-
-         @Override
-         protected void configure() {
-            bind(SharedKeyLiteAuthentication.class).toInstance(createMock(SharedKeyLiteAuthentication.class));
-         }
-
-      }).getInstance(ParseAzureStorageErrorFromXmlContent.class);
-
-      HttpCommand command = createMock(HttpCommand.class);
-      HttpRequest request = HttpRequest.builder().method(method).endpoint(uri).build();
-      HttpResponse response = HttpResponse.builder().statusCode(statusCode).message(message).payload(content).build();
-      response.getPayload().getContentMetadata().setContentType(contentType);
-
-      expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
-      command.setException(classEq(expected));
-
-      replay(command);
-
-      function.handleError(command, response);
-
-      verify(command);
-   }
-
-   public static Exception classEq(final Class<? extends Exception> in) {
-      reportMatcher(new IArgumentMatcher() {
-
-         @Override
-         public void appendTo(StringBuffer buffer) {
-            buffer.append("classEq(");
-            buffer.append(in);
-            buffer.append(")");
-         }
-
-         @Override
-         public boolean matches(Object arg) {
-            return arg.getClass() == in;
-         }
-
-      });
-      return null;
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/test/java/org/jclouds/azure/storage/options/CreateOptionsTest.java
----------------------------------------------------------------------
diff --git a/common/azure/src/test/java/org/jclouds/azure/storage/options/CreateOptionsTest.java b/common/azure/src/test/java/org/jclouds/azure/storage/options/CreateOptionsTest.java
deleted file mode 100644
index b582783..0000000
--- a/common/azure/src/test/java/org/jclouds/azure/storage/options/CreateOptionsTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.options;
-
-import static org.testng.Assert.assertEquals;
-
-import org.jclouds.azure.storage.reference.AzureStorageHeaders;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMultimap;
-
-/**
- * Tests behavior of {@code CreateOptions}
- */
-@Test(groups = "unit")
-public class CreateOptionsTest {
-
-   public void testMetadata() {
-      CreateOptions options = new CreateOptions().withMetadata(ImmutableMultimap.of(
-               "test", "foo"));
-      assertEquals(ImmutableList.of("foo"), options.buildRequestHeaders().get(
-               AzureStorageHeaders.USER_METADATA_PREFIX + "test"));
-   }
-
-   public void testMetadataAlreadyPrefixed() {
-      CreateOptions options = new CreateOptions().withMetadata(ImmutableMultimap.of(
-               AzureStorageHeaders.USER_METADATA_PREFIX + "test", "foo"));
-      assertEquals(ImmutableList.of("foo"), options.buildRequestHeaders().get(
-               AzureStorageHeaders.USER_METADATA_PREFIX + "test"));
-   }
-
-   public void testMetadataStatic() {
-      CreateOptions options = CreateOptions.Builder.withMetadata(ImmutableMultimap.of(
-               "test", "foo"));
-      assertEquals(ImmutableList.of("foo"), options.buildRequestHeaders().get(
-               AzureStorageHeaders.USER_METADATA_PREFIX + "test"));
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/test/java/org/jclouds/azure/storage/options/ListOptionsTest.java
----------------------------------------------------------------------
diff --git a/common/azure/src/test/java/org/jclouds/azure/storage/options/ListOptionsTest.java b/common/azure/src/test/java/org/jclouds/azure/storage/options/ListOptionsTest.java
deleted file mode 100644
index 67fc768..0000000
--- a/common/azure/src/test/java/org/jclouds/azure/storage/options/ListOptionsTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.options;
-
-import static org.testng.Assert.assertEquals;
-
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-
-/**
- * Tests behavior of {@code ListOptions}
- */
-@Test(groups = "unit")
-public class ListOptionsTest {
-   public void testIncludeMetadata() {
-      ListOptions options = new ListOptions().includeMetadata();
-      assertEquals(ImmutableList.of("metadata"), options.buildQueryParameters().get("include"));
-   }
-
-   public void testIncludeMetadataStatic() {
-      ListOptions options = ListOptions.Builder.includeMetadata();
-      assertEquals(ImmutableList.of("metadata"), options.buildQueryParameters().get("include"));
-   }
-
-   public void testPrefix() {
-      ListOptions options = new ListOptions().prefix("a");
-      assertEquals(ImmutableList.of("a"), options.buildQueryParameters().get("prefix"));
-   }
-
-   public void testMarker() {
-      ListOptions options = new ListOptions().marker("a");
-      assertEquals(ImmutableList.of("a"), options.buildQueryParameters().get("marker"));
-   }
-
-   public void testMaxResults() {
-      int limit = 1;
-      ListOptions options = new ListOptions().maxResults(limit);
-      assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("maxresults"));
-   }
-
-   public void testPrefixStatic() {
-      ListOptions options = ListOptions.Builder.prefix("a");
-      assertEquals(ImmutableList.of("a"), options.buildQueryParameters().get("prefix"));
-   }
-
-   public void testMarkerStatic() {
-      ListOptions options = ListOptions.Builder.marker("a");
-      assertEquals(ImmutableList.of("a"), options.buildQueryParameters().get("marker"));
-   }
-
-   public void testMaxResultsStatic() {
-      int limit = 1;
-      ListOptions options = ListOptions.Builder.maxResults(limit);
-      assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("maxresults"));
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/test/java/org/jclouds/azure/storage/xml/ErrorHandlerTest.java
----------------------------------------------------------------------
diff --git a/common/azure/src/test/java/org/jclouds/azure/storage/xml/ErrorHandlerTest.java b/common/azure/src/test/java/org/jclouds/azure/storage/xml/ErrorHandlerTest.java
deleted file mode 100644
index 1698cd6..0000000
--- a/common/azure/src/test/java/org/jclouds/azure/storage/xml/ErrorHandlerTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.azure.storage.xml;
-
-import static org.testng.Assert.assertEquals;
-
-import java.io.InputStream;
-
-import org.jclouds.azure.storage.domain.AzureStorageError;
-import org.jclouds.http.functions.BaseHandlerTest;
-import org.jclouds.http.functions.ParseSax;
-import org.testng.annotations.Test;
-
-/**
- * Tests behavior of {@code ErrorHandler}
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "ErrorHandlerTest")
-public class ErrorHandlerTest extends BaseHandlerTest {
-
-   ParseSax<AzureStorageError> createParser() {
-      ParseSax<AzureStorageError> parser = factory.create(injector
-               .getInstance(ErrorHandler.class));
-      return parser;
-   }
-
-   public void testApplyInputStream() {
-      InputStream is = getClass().getResourceAsStream("/test_error.xml");
-      ParseSax<AzureStorageError> parser = createParser();
-      AzureStorageError result = parser.parse(is);
-      assertEquals(result.getCode(), "AuthenticationFailed");
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/test/resources/log4j.xml
----------------------------------------------------------------------
diff --git a/common/azure/src/test/resources/log4j.xml b/common/azure/src/test/resources/log4j.xml
deleted file mode 100644
index acaa72d..0000000
--- a/common/azure/src/test/resources/log4j.xml
+++ /dev/null
@@ -1,118 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-
-    <!--
-        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">
-
-    <!-- A time/date based rolling appender -->
-    <appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
-        <param name="File" value="target/test-data/jclouds-wire.log" />
-        <param name="Append" value="true" />
-
-        <!-- Rollover at midnight each day -->
-        <param name="DatePattern" value="'.'yyyy-MM-dd" />
-
-        <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" />
-
-            <!--
-                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" />
-
-        <!-- Rollover at midnight each day -->
-        <param name="DatePattern" value="'.'yyyy-MM-dd" />
-
-        <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" />
-
-            <!--
-                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>
-
-    <!-- A time/date based rolling appender -->
-    <appender name="BLOBSTOREFILE" class="org.apache.log4j.DailyRollingFileAppender">
-        <param name="File" value="target/test-data/jclouds-blobstore.log" />
-        <param name="Append" value="true" />
-
-        <!-- Rollover at midnight each day -->
-        <param name="DatePattern" value="'.'yyyy-MM-dd" />
-
-        <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" />
-
-            <!--
-                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="ASYNCBLOBSTORE" class="org.apache.log4j.AsyncAppender">
-        <appender-ref ref="BLOBSTOREFILE" />
-    </appender>
-    <!-- ================ -->
-    <!-- Limit categories -->
-    <!-- ================ -->
-    <category name="jclouds.blobstore">
-        <priority value="TRACE" />
-        <appender-ref ref="ASYNCBLOBSTORE" />
-    </category>
-
-    <category name="org.jclouds">
-        <priority value="DEBUG" />
-        <appender-ref ref="ASYNC" />
-    </category>
-
-    <category name="jclouds.headers">
-        <priority value="DEBUG" />
-        <appender-ref ref="ASYNCWIRE" />
-    </category>
-
-    <category name="jclouds.wire">
-        <priority value="DEBUG" />
-        <appender-ref ref="ASYNCWIRE" />
-    </category>
-    <!-- ======================= -->
-    <!-- Setup the Root category -->
-    <!-- ======================= -->
-
-    <root>
-        <priority value="WARN" />
-    </root>
-
-</log4j:configuration>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/azure/src/test/resources/test_error.xml
----------------------------------------------------------------------
diff --git a/common/azure/src/test/resources/test_error.xml b/common/azure/src/test/resources/test_error.xml
deleted file mode 100644
index 6c12fac..0000000
--- a/common/azure/src/test/resources/test_error.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Error>
-	<Code>AuthenticationFailed</Code>
-	<Message>Server failed to authenticate the request. Make sure the value
-		of Authorization header is formed correctly including the signature.
-		RequestId:7859e884-e8b9-4ed0-aa62-ac6963b91bf6
-		Time:2009-09-02T23:32:36.7507749Z</Message>
-	<AuthenticationErrorDetail>The MAC signature found in the HTTP request
-		'XEv0NqP+zePZxlrHmxy2F6MiyoRD8LIJt1f/Swgzn1U=' is not the same as any
-		computed signature. Server used following string to sign: 'GET
-
-
-		Wed, 02 Sep 2009 23:32:34 GMT
-		/jclouds/?comp=list'.</AuthenticationErrorDetail>
-</Error>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/common/pom.xml
----------------------------------------------------------------------
diff --git a/common/pom.xml b/common/pom.xml
index 36c0774..e92dc51 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -30,7 +30,6 @@
   <packaging>pom</packaging>
   <name>jclouds commons project</name>
   <modules>
-    <module>azure</module>
     <module>openstack</module>
   </modules>
 </project>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6843e0cb/providers/azureblob/pom.xml
----------------------------------------------------------------------
diff --git a/providers/azureblob/pom.xml b/providers/azureblob/pom.xml
index b6e4676..30aff3a 100644
--- a/providers/azureblob/pom.xml
+++ b/providers/azureblob/pom.xml
@@ -38,7 +38,7 @@
     <test.azureblob.identity>${test.azure.identity}</test.azureblob.identity>
     <test.azureblob.credential>${test.azure.credential}</test.azureblob.credential>
 
-    <jclouds.osgi.export>org.jclouds.azureblob*;version="${project.version}"</jclouds.osgi.export>
+    <jclouds.osgi.export>org.jclouds.azureblob*;version="${project.version}",org.jclouds.azure.storage*;version="${project.version}"</jclouds.osgi.export>
     <jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
   </properties>