Issue 86: added blobstore support for azure

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2016 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-10-31 00:52:06 +00:00
parent bcd1c2343a
commit 0c7ac791dc
45 changed files with 1732 additions and 100 deletions

View File

@ -36,10 +36,10 @@ import javax.ws.rs.PathParam;
import org.jclouds.azure.storage.AzureBlob;
import org.jclouds.azure.storage.blob.binders.BindAzureBlobToEntity;
import org.jclouds.azure.storage.blob.blobstore.functions.BlobName;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableContainerProperties;
import org.jclouds.azure.storage.blob.functions.BlobName;
import org.jclouds.azure.storage.blob.functions.ParseBlobFromHeadersAndHttpContent;
import org.jclouds.azure.storage.blob.functions.ParseBlobPropertiesFromHeaders;
import org.jclouds.azure.storage.blob.functions.ParseContainerPropertiesFromHeaders;
@ -48,7 +48,7 @@ import org.jclouds.azure.storage.blob.options.CreateContainerOptions;
import org.jclouds.azure.storage.blob.options.ListBlobsOptions;
import org.jclouds.azure.storage.blob.xml.AccountNameEnumerationResultsHandler;
import org.jclouds.azure.storage.blob.xml.ContainerNameEnumerationResultsHandler;
import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.reference.AzureStorageHeaders;
@ -56,6 +56,7 @@ import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.http.functions.ReturnTrueOn404;
import org.jclouds.http.options.GetOptions;
import org.jclouds.rest.annotations.BinderParam;
@ -98,7 +99,8 @@ public interface AzureBlobClient {
@XMLResponseParser(AccountNameEnumerationResultsHandler.class)
@Path("/")
@QueryParams(keys = "comp", values = "list")
BoundedList<ListableContainerProperties> listContainers(ListOptions... listOptions);
Future<? extends BoundedSortedSet<ListableContainerProperties>> listContainers(
ListOptions... listOptions);
/**
* The Create Container operation creates a new container under the specified account. If the
@ -127,6 +129,15 @@ public interface AzureBlobClient {
@ResponseParser(ParseContainerPropertiesFromHeaders.class)
ListableContainerProperties getContainerProperties(@PathParam("container") String container);
/**
* Issues a HEAD command to determine if the container exists or not.
*/
@HEAD
@Path("{container}")
@QueryParams(keys = "restype", values = "container")
@ExceptionParser(ReturnFalseOn404.class)
boolean containerExists(@PathParam("container") String container);
/**
* The Set Container Metadata operation sets one or more user-defined name/value pairs for the
* specified container. <h4>Remarks</h4>
@ -290,9 +301,7 @@ public interface AzureBlobClient {
* 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.
*/
@GET
@Headers(keys = "Range", values = "bytes=0-0")
// should use HEAD, this is a hack per http://code.google.com/p/jclouds/issues/detail?id=92
@HEAD
@ResponseParser(ParseBlobPropertiesFromHeaders.class)
@ExceptionParser(ThrowKeyNotFoundOn404.class)
@Path("{container}/{name}")

View File

@ -0,0 +1,174 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.blobstore.options.ListOptions.Builder.recursive;
import java.util.SortedSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.inject.Inject;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.azure.storage.blob.blobstore.functions.AzureBlobToBlob;
import org.jclouds.azure.storage.blob.blobstore.functions.BlobPropertiesToBlobMetadata;
import org.jclouds.azure.storage.blob.blobstore.functions.BlobToAzureBlob;
import org.jclouds.azure.storage.blob.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.azure.storage.blob.blobstore.functions.ContainerToResourceMetadata;
import org.jclouds.azure.storage.blob.blobstore.functions.ListBlobsResponseToResourceList;
import org.jclouds.azure.storage.blob.blobstore.functions.ListOptionsToListBlobsOptions;
import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableContainerProperties;
import org.jclouds.azure.storage.blob.options.ListBlobsOptions;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.attr.ConsistencyModels;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.BoundedSortedSet;
import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.options.ListOptions;
import org.jclouds.blobstore.strategy.ClearListStrategy;
import org.jclouds.concurrent.FutureFunctionWrapper;
import org.jclouds.http.options.GetOptions;
import org.jclouds.logging.Logger.LoggerFactory;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
@ConsistencyModel(ConsistencyModels.STRICT)
public class AzureBlobStore implements BlobStore {
private final AzureBlobClient connection;
private final Blob.Factory blobFactory;
private final LoggerFactory logFactory;
private final ClearListStrategy clearContainerStrategy;
private final BlobPropertiesToBlobMetadata object2BlobMd;
private final AzureBlobToBlob object2Blob;
private final BlobToAzureBlob blob2Object;
private final ListOptionsToListBlobsOptions container2ContainerListOptions;
private final BlobToHttpGetOptions blob2ObjectGetOptions;
private final ContainerToResourceMetadata container2ResourceMd;
private final ListBlobsResponseToResourceList container2ResourceList;
private final ExecutorService service;
@Inject
private AzureBlobStore(AzureBlobClient connection, Blob.Factory blobFactory, LoggerFactory logFactory,
ClearListStrategy clearContainerStrategy, BlobPropertiesToBlobMetadata object2BlobMd,
AzureBlobToBlob object2Blob, BlobToAzureBlob blob2Object,
ListOptionsToListBlobsOptions container2ContainerListOptions,
BlobToHttpGetOptions blob2ObjectGetOptions,
ContainerToResourceMetadata container2ResourceMd, ListBlobsResponseToResourceList container2ResourceList,
ExecutorService service) {
this.connection = checkNotNull(connection, "connection");
this.blobFactory = checkNotNull(blobFactory, "blobFactory");
this.logFactory = checkNotNull(logFactory, "logFactory");
this.clearContainerStrategy = checkNotNull(clearContainerStrategy, "clearContainerStrategy");
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions,
"container2ContainerListOptions");
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd");
this.container2ResourceList = checkNotNull(container2ResourceList, "container2ResourceList");
this.service = checkNotNull(service, "service");
}
protected <F, T> Future<T> wrapFuture(Future<? extends F> future, Function<F, T> function) {
return new FutureFunctionWrapper<F, T>(future, function, logFactory.getLogger(function
.getClass().getName()));
}
/**
* This implementation uses the AzureBlob HEAD Object command to return the result
*/
public BlobMetadata blobMetadata(String container, String key) {
return object2BlobMd.apply(connection.getBlobProperties(container, key));
}
public Future<Void> clearContainer(final String container) {
return service.submit(new Callable<Void>() {
public Void call() throws Exception {
clearContainerStrategy.execute(container, recursive());
return null;
}
});
}
public Future<Boolean> createContainer(String container) {
return connection.createContainer(container);
}
public Future<Void> deleteContainer(final String container) {
return connection.deleteContainer(container);
}
public boolean exists(String container) {
return connection.containerExists(container);
}
public Future<Blob> getBlob(String container, String key,
org.jclouds.blobstore.options.GetOptions... optionsList) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList);
Future<AzureBlob> returnVal = connection.getBlob(container, key, httpOptions);
return wrapFuture(returnVal, object2Blob);
}
public Future<? extends SortedSet<? extends ResourceMetadata>> list() {
return wrapFuture(connection.listContainers(),
new Function<SortedSet<ListableContainerProperties>, SortedSet<? extends ResourceMetadata>>() {
public SortedSet<? extends ResourceMetadata> apply(SortedSet<ListableContainerProperties> from) {
return Sets.newTreeSet(Iterables.transform(from, container2ResourceMd));
}
});
}
public Future<? extends BoundedSortedSet<? extends ResourceMetadata>> list(String container,
ListOptions... optionsList) {
ListBlobsOptions httpOptions = container2ContainerListOptions.apply(optionsList);
Future<ListBlobsResponse> returnVal = connection.listBlobs(container, httpOptions);
return wrapFuture(returnVal, container2ResourceList);
}
public Future<String> putBlob(String container, Blob blob) {
return connection.putBlob(container, blob2Object.apply(blob));
}
public Future<Void> removeBlob(String container, String key) {
return connection.deleteBlob(container, key);
}
public Blob newBlob() {
return blobFactory.create(null);
}
}

View File

@ -0,0 +1,80 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.azure.storage.blob.blobstore.config.AzureBlobStoreContextModule;
import org.jclouds.azure.storage.blob.config.AzureBlobRestClientModule;
import org.jclouds.blobstore.BlobStoreContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Creates {@link AzureBlobStoreContext} or {@link Injector} instances based on the most commonly
* requested arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/>
* <p/>
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole, Andrew Newdigate
* @see AzureBlobStoreContext
*/
public class AzureBlobStoreContextBuilder extends BlobStoreContextBuilder<AzureBlobClient> {
public AzureBlobStoreContextBuilder(Properties props) {
super(new TypeLiteral<AzureBlobClient>() {
}, props);
}
@Override
public AzureBlobStoreContextBuilder withExecutorService(ExecutorService service) {
return (AzureBlobStoreContextBuilder) super.withExecutorService(service);
}
@Override
public AzureBlobStoreContextBuilder withModules(Module... modules) {
return (AzureBlobStoreContextBuilder) super.withModules(modules);
}
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new AzureBlobStoreContextModule());
}
@Override
protected void addClientModule(List<Module> modules) {
modules.add(new AzureBlobRestClientModule());
}
}

View File

@ -0,0 +1,68 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore;
import java.net.URI;
import java.util.Properties;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.inject.Module;
/**
* Creates {@link AzureBlobStoreContext} instances based on the most commonly requested
* arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/>
* <p/>
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole, Andrew Newdigate
* @see AzureBlobStoreContext
*/
public class AzureBlobStoreContextFactory {
public static BlobStoreContext<AzureBlobClient> createContext(Properties properties,
Module... modules) {
return new AzureBlobStoreContextBuilder(new AzureBlobStorePropertiesBuilder(
properties).build()).withModules(modules).buildContext();
}
public static BlobStoreContext<AzureBlobClient> createContext(String user,
String encodedKey, Module... modules) {
return new AzureBlobStoreContextBuilder(new AzureBlobStorePropertiesBuilder(
user, encodedKey).build()).withModules(modules).buildContext();
}
public static BlobStoreContext<AzureBlobClient> createContext(URI endpoint,
String user, String encodedKey, Module... modules) {
return new AzureBlobStoreContextBuilder(new AzureBlobStorePropertiesBuilder(
user, encodedKey).withEndpoint(endpoint).build()).withModules(
modules).buildContext();
}
}

View File

@ -0,0 +1,55 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore;
import java.util.Properties;
import org.jclouds.azure.storage.blob.AzureBlobPropertiesBuilder;
import org.jclouds.blobstore.reference.BlobStoreConstants;
/**
* Builds properties used in AzureBlob Blob Stores
*
* @author Adrian Cole, Andrew Newdigate
*/
public class AzureBlobStorePropertiesBuilder extends AzureBlobPropertiesBuilder {
public AzureBlobStorePropertiesBuilder(String id, String secret) {
super(id, secret);
}
public AzureBlobStorePropertiesBuilder(Properties properties) {
super(properties);
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public AzureBlobStorePropertiesBuilder withRequestTimeout(long milliseconds) {
properties.setProperty(BlobStoreConstants.PROPERTY_BLOBSTORE_TIMEOUT, Long
.toString(milliseconds));
return this;
}
}

View File

@ -0,0 +1,76 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.config;
import java.net.URI;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.azure.storage.AzureBlob;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStore;
import org.jclouds.azure.storage.blob.blobstore.strategy.FindMD5InBlobProperties;
import org.jclouds.azure.storage.blob.config.AzureBlobModule;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.blobstore.BlobMap;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.InputStreamMap;
import org.jclouds.blobstore.config.BlobStoreMapModule;
import org.jclouds.blobstore.config.BlobStoreObjectModule;
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
import org.jclouds.lifecycle.Closer;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/**
* Configures the {@link AzureBlobStoreContext}; requires {@link AzureBlobStore} bound.
*
* @author Adrian Cole
*/
public class AzureBlobStoreContextModule extends AbstractModule {
@Override
protected void configure() {
install(new BlobStoreObjectModule());
install(new BlobStoreMapModule());
install(new AzureBlobModule());
bind(BlobStore.class).to(AzureBlobStore.class).asEagerSingleton();
bind(ContainsValueInListStrategy.class).to(FindMD5InBlobProperties.class);
}
@Provides
@Singleton
BlobStoreContext<AzureBlobClient> provideContext(BlobMap.Factory blobMapFactory,
InputStreamMap.Factory inputStreamMapFactory, Closer closer, BlobStore blobStore,
AzureBlobClient defaultApi, @AzureBlob URI endPoint,
@Named(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT) String account) {
return new BlobStoreContextImpl<AzureBlobClient>(blobMapFactory, inputStreamMapFactory,
closer, blobStore, defaultApi, endPoint, account);
}
}

View File

@ -4,29 +4,18 @@ import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.ResourceType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class BlobPropertiesToBlobMetadata implements Function<BlobProperties, MutableBlobMetadata> {
public class BlobPropertiesToBlobMetadata extends
ListableBlobPropertiesToBlobMetadata<BlobProperties> {
@Override
public MutableBlobMetadata apply(BlobProperties from) {
MutableBlobMetadata to = new MutableBlobMetadataImpl();
MutableBlobMetadata to = super.apply(from);
to.setContentMD5(from.getContentMD5());
if (from.getContentType() != null)
to.setContentType(from.getContentType());
to.setETag(from.getETag());
to.setName(from.getName());
to.setSize(from.getSize());
to.setType(ResourceType.BLOB);
to.setUserMetadata(from.getMetadata());
if (from.getContentType() != null && from.getContentType().equals("application/directory")) {
to.setType(ResourceType.RELATIVE_PATH);
}
return to;
}
}

View File

@ -0,0 +1,33 @@
package org.jclouds.azure.storage.blob.blobstore.functions;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.blobstore.domain.Blob;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class BlobToAzureBlob implements Function<Blob, AzureBlob> {
private final BlobMetadataToBlobProperties blob2ObjectMd;
private final AzureBlob.Factory objectProvider;
@Inject
BlobToAzureBlob(BlobMetadataToBlobProperties blob2ObjectMd, AzureBlob.Factory objectProvider) {
this.blob2ObjectMd = blob2ObjectMd;
this.objectProvider = objectProvider;
}
public AzureBlob apply(Blob from) {
AzureBlob object = objectProvider.create(blob2ObjectMd.apply(from.getMetadata()));
if (from.getContentLength() != null)
object.setContentLength(from.getContentLength());
object.setData(from.getData());
object.setAllHeaders(from.getAllHeaders());
return object;
}
}

View File

@ -0,0 +1,60 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.http.options.GetOptions;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class BlobToHttpGetOptions implements
Function<org.jclouds.blobstore.options.GetOptions[], GetOptions> {
public GetOptions apply(org.jclouds.blobstore.options.GetOptions[] from) {
GetOptions httpOptions = new GetOptions();
if (from.length != 0) {
if (from[0].getIfMatch() != null) {
httpOptions.ifETagMatches(from[0].getIfMatch());
}
if (from[0].getIfModifiedSince() != null) {
httpOptions.ifModifiedSince(from[0].getIfModifiedSince());
}
if (from[0].getIfNoneMatch() != null) {
httpOptions.ifETagDoesntMatch(from[0].getIfNoneMatch());
}
if (from[0].getIfUnmodifiedSince() != null) {
httpOptions.ifUnmodifiedSince(from[0].getIfUnmodifiedSince());
}
for (String range : from[0].getRanges()) {
String[] firstLast = range.split("\\-");
httpOptions.range(Long.parseLong(firstLast[0]), Long.parseLong(firstLast[1]));
}
}
return httpOptions;
}
}

View File

@ -0,0 +1,54 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.blobstore.domain.MutableResourceMetadata;
import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.domain.ResourceType;
import org.jclouds.blobstore.domain.internal.MutableResourceMetadataImpl;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
*/
@Singleton
public class CommonPrefixesToResourceMetadata implements
Function<Iterable<String>, Iterable<ResourceMetadata>> {
public Iterable<ResourceMetadata> apply(
Iterable<String> prefixes) {
return Iterables.transform(prefixes, new Function<String, ResourceMetadata>() {
public ResourceMetadata apply(String from) {
MutableResourceMetadata returnVal = new MutableResourceMetadataImpl();
returnVal.setType(ResourceType.RELATIVE_PATH);
returnVal.setName(from);
return returnVal;
}
});
}
}

View File

@ -0,0 +1,50 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.domain.ListableContainerProperties;
import org.jclouds.blobstore.domain.MutableResourceMetadata;
import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.domain.ResourceType;
import org.jclouds.blobstore.domain.internal.MutableResourceMetadataImpl;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class ContainerToResourceMetadata implements Function<ListableContainerProperties, ResourceMetadata> {
public ResourceMetadata apply(ListableContainerProperties from) {
MutableResourceMetadata to = new MutableResourceMetadataImpl();
to.setName(from.getName());
to.setETag(from.getETag());
to.setLastModified(from.getLastModified());
to.setLocation(from.getUrl());
to.setType(ResourceType.CONTAINER);
return to;
}
}

View File

@ -0,0 +1,58 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.options.ListBlobsOptions;
import org.jclouds.blobstore.options.ListOptions;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class ListBlobsOptionsToListOptions implements Function<ListBlobsOptions[], ListOptions> {
public ListOptions apply(ListBlobsOptions[] optionsList) {
ListOptions options = new ListOptions();
if (optionsList.length != 0) {
if (optionsList[0].getDelimiter() == null) {
options.recursive();
} else if (!optionsList[0].getDelimiter().equals("/")) {
throw new IllegalArgumentException("only '/' is allowed as a blobstore delimiter");
}
if (optionsList[0].getMarker() != null) {
options.afterMarker(optionsList[0].getMarker());
}
if (optionsList[0].getMaxResults() != null) {
options.maxResults(optionsList[0].getMaxResults());
}
if (optionsList[0].getPrefix() != null) {
options.underPath(optionsList[0].getPrefix());
}
}
return options;
}
}

View File

@ -0,0 +1,65 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.functions;
import java.util.SortedSet;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableBlobProperties;
import org.jclouds.blobstore.domain.BoundedSortedSet;
import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.domain.internal.BoundedTreeSet;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
* @author Adrian Cole
*/
@Singleton
public class ListBlobsResponseToResourceList implements
Function<ListBlobsResponse, BoundedSortedSet<? extends ResourceMetadata>> {
private final ListableBlobPropertiesToBlobMetadata<ListableBlobProperties> object2blobMd;
private final CommonPrefixesToResourceMetadata prefix2ResourceMd;
@Inject
public ListBlobsResponseToResourceList(
ListableBlobPropertiesToBlobMetadata<ListableBlobProperties> object2blobMd,
CommonPrefixesToResourceMetadata prefix2ResourceMd) {
this.object2blobMd = object2blobMd;
this.prefix2ResourceMd = prefix2ResourceMd;
}
public BoundedSortedSet<? extends ResourceMetadata> apply(ListBlobsResponse from) {
SortedSet<ResourceMetadata> contents = Sets.newTreeSet(Iterables.concat(Iterables.transform(
from, object2blobMd), prefix2ResourceMd.apply(from.getBlobPrefixes())));
return new BoundedTreeSet<ResourceMetadata>(contents, from.getPrefix(), from.getMarker(),
from.getMaxResults(), from.size() == from.getMaxResults());
}
}

View File

@ -0,0 +1,56 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.options.ListBlobsOptions;
import org.jclouds.blobstore.options.ListOptions;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class ListOptionsToListBlobsOptions implements Function<ListOptions[], ListBlobsOptions> {
public ListBlobsOptions apply(ListOptions[] optionsList) {
ListBlobsOptions httpOptions = new ListBlobsOptions();
if (optionsList.length != 0) {
if (!optionsList[0].isRecursive()) {
httpOptions.delimiter("/");
}
if (optionsList[0].getPath() != null) {
httpOptions.prefix(optionsList[0].getPath());
}
if (optionsList[0].getMarker() != null) {
httpOptions.marker(optionsList[0].getMarker());
}
if (optionsList[0].getMaxResults() != null) {
httpOptions.maxResults(optionsList[0].getMaxResults());
}
}
return httpOptions;
}
}

View File

@ -0,0 +1,31 @@
package org.jclouds.azure.storage.blob.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.domain.ListableBlobProperties;
import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.ResourceType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class ListableBlobPropertiesToBlobMetadata<T extends ListableBlobProperties> implements
Function<T, MutableBlobMetadata> {
public MutableBlobMetadata apply(T from) {
MutableBlobMetadata to = new MutableBlobMetadataImpl();
if (from.getContentType() != null)
to.setContentType(from.getContentType());
to.setETag(from.getETag());
to.setName(from.getName());
to.setSize(from.getSize());
to.setType(ResourceType.BLOB);
if (from.getContentType() != null && from.getContentType().equals("application/directory")) {
to.setType(ResourceType.RELATIVE_PATH);
}
return to;
}
}

View File

@ -0,0 +1,92 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.functions;
import java.util.SortedSet;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableBlobProperties;
import org.jclouds.azure.storage.blob.domain.MutableBlobProperties;
import org.jclouds.azure.storage.blob.domain.internal.TreeSetListBlobsResponse;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.BoundedSortedSet;
import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.domain.ResourceType;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
* @author Adrian Cole
*/
@Singleton
public class ResourceToListBlobsResponse implements
Function<BoundedSortedSet<? extends ResourceMetadata>, ListBlobsResponse> {
private final BlobMetadataToBlobProperties blob2ObjectMd;
@Inject
public ResourceToListBlobsResponse(BlobMetadataToBlobProperties blob2ObjectMd) {
this.blob2ObjectMd = blob2ObjectMd;
}
public ListBlobsResponse apply(BoundedSortedSet<? extends ResourceMetadata> list) {
Iterable<ListableBlobProperties> contents = Iterables.transform(Iterables.filter(list,
new Predicate<ResourceMetadata>() {
public boolean apply(ResourceMetadata input) {
return input.getType() == ResourceType.BLOB;
}
}), new Function<ResourceMetadata, ListableBlobProperties>() {
public MutableBlobProperties apply(ResourceMetadata from) {
return blob2ObjectMd.apply((BlobMetadata) from);
}
});
SortedSet<String> commonPrefixes = Sets.newTreeSet(Iterables.transform(Iterables.filter(list,
new Predicate<ResourceMetadata>() {
public boolean apply(ResourceMetadata input) {
return input.getType() == ResourceType.RELATIVE_PATH;
}
}), new Function<ResourceMetadata, String>() {
public String apply(ResourceMetadata from) {
return from.getName();
}
}));
return new TreeSetListBlobsResponse(contents, null, list.getPath(), null, list
.getMaxResults(),list.getMarker(), "/", commonPrefixes);
}
}

View File

@ -0,0 +1,55 @@
package org.jclouds.azure.storage.blob.blobstore.strategy;
import java.util.Arrays;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.functions.ObjectMD5;
import org.jclouds.blobstore.internal.BlobRuntimeException;
import org.jclouds.blobstore.options.ListOptions;
import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
import org.jclouds.blobstore.strategy.ListBlobMetadataStrategy;
import org.jclouds.util.Utils;
/**
* Searches Content-MD5 tag for the value associated with the value
*
* @author Adrian Cole
*/
@Singleton
public class FindMD5InBlobProperties implements ContainsValueInListStrategy {
protected final ObjectMD5 objectMD5;
protected final ListBlobMetadataStrategy getAllBlobMetadata;
private final AzureBlobClient client;
@Inject
private FindMD5InBlobProperties(ObjectMD5 objectMD5,
ListBlobMetadataStrategy getAllBlobMetadata, AzureBlobClient client) {
this.objectMD5 = objectMD5;
this.getAllBlobMetadata = getAllBlobMetadata;
this.client = client;
}
public boolean execute(String containerName, Object value, ListOptions options) {
try {
byte[] toSearch = objectMD5.apply(value);
for (BlobMetadata metadata : getAllBlobMetadata.execute(containerName, options)) {
BlobProperties properties = client.getBlobProperties(containerName, metadata.getName());
if (Arrays.equals(toSearch, properties.getContentMD5()))
return true;
}
return false;
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format(
"Error searching for ETAG of value: [%2$s] in container:%1$s", containerName,
value), e);
}
}
}

View File

@ -25,13 +25,13 @@ package org.jclouds.azure.storage.blob.domain;
import java.util.SortedSet;
import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
/**
*
* @author Adrian Cole
*/
public interface ListBlobsResponse extends BoundedList<ListableBlobProperties> {
public interface ListBlobsResponse extends BoundedSortedSet<ListableBlobProperties> {
String getDelimiter();

View File

@ -40,7 +40,7 @@ public class TreeSetListBlobsResponse extends BoundedTreeSet<ListableBlobPropert
/** The serialVersionUID */
private static final long serialVersionUID = -4475709781001190244L;
public TreeSetListBlobsResponse(SortedSet<ListableBlobProperties> contents, URI url, String prefix,
public TreeSetListBlobsResponse(Iterable<ListableBlobProperties> contents, URI url, String prefix,
String marker, Integer maxResults, String nextMarker, String delimiter,
SortedSet<String> blobPrefixes) {
super(contents, url, prefix, marker, maxResults, nextMarker);

View File

@ -1,4 +1,4 @@
package org.jclouds.azure.storage.blob.blobstore.functions;
package org.jclouds.azure.storage.blob.functions;
import org.jclouds.azure.storage.blob.domain.AzureBlob;

View File

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

View File

@ -57,6 +57,10 @@ public class ListBlobsOptions extends ListOptions {
return this;
}
public String getDelimiter() {
return this.getFirstQueryOrNull("delimiter");
}
public static class Builder {
/**

View File

@ -30,7 +30,7 @@ import javax.inject.Inject;
import org.jclouds.azure.storage.blob.domain.ListableContainerProperties;
import org.jclouds.azure.storage.blob.domain.internal.ListableContainerPropertiesImpl;
import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.internal.BoundedTreeSet;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.DateService;
@ -47,7 +47,7 @@ import com.google.common.collect.Sets;
* @author Adrian Cole
*/
public class AccountNameEnumerationResultsHandler extends
ParseSax.HandlerWithResult<BoundedList<ListableContainerProperties>> {
ParseSax.HandlerWithResult<BoundedSortedSet<ListableContainerProperties>> {
private SortedSet<ListableContainerProperties> containerMetadata = Sets.newTreeSet();
private String prefix;
@ -67,7 +67,7 @@ public class AccountNameEnumerationResultsHandler extends
this.dateParser = dateParser;
}
public BoundedList<ListableContainerProperties> getResult() {
public BoundedSortedSet<ListableContainerProperties> getResult() {
return new BoundedTreeSet<ListableContainerProperties>(containerMetadata, currentUrl, prefix, marker,
maxResults, nextMarker);
}

View File

@ -109,7 +109,7 @@ public class ContainerNameEnumerationResultsHandler extends
prefix = (prefix.equals("")) ? null : prefix;
} else if (qName.equals("Delimiter")) {
delimiter = currentText.toString().trim();
delimiter = (prefix.equals("")) ? null : delimiter;
delimiter = (delimiter.equals("")) ? null : delimiter;
} else if (qName.equals("NextMarker")) {
nextMarker = currentText.toString().trim();
nextMarker = (nextMarker.equals("")) ? null : nextMarker;

View File

@ -43,7 +43,7 @@ import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableContainerProperties;
import org.jclouds.azure.storage.blob.options.CreateContainerOptions;
import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.HttpUtils;
@ -78,7 +78,8 @@ public class AzureBlobClientLiveTest {
@Test
public void testListContainers() throws Exception {
SortedSet<ListableContainerProperties> response = connection.listContainers();
SortedSet<ListableContainerProperties> response = connection.listContainers().get(10,
TimeUnit.SECONDS);
assert null != response;
long initialContainerCount = response.size();
assertTrue(initialContainerCount >= 0);
@ -107,7 +108,8 @@ public class AzureBlobClientLiveTest {
throw e;
}
}
SortedSet<ListableContainerProperties> response = connection.listContainers();
SortedSet<ListableContainerProperties> response = connection.listContainers().get(10,
TimeUnit.SECONDS);
assert null != response;
long containerCount = response.size();
assertTrue(containerCount >= 1);
@ -175,8 +177,9 @@ public class AzureBlobClientLiveTest {
@Test
public void testListContainersWithOptions() throws Exception {
BoundedList<ListableContainerProperties> response = connection
.listContainers(ListOptions.Builder.prefix(privateContainer).maxResults(1));
BoundedSortedSet<ListableContainerProperties> response = connection.listContainers(
ListOptions.Builder.prefix(privateContainer).maxResults(1))
.get(10, TimeUnit.SECONDS);
assert null != response;
long initialContainerCount = response.size();
assertTrue(initialContainerCount >= 0);
@ -195,18 +198,22 @@ public class AzureBlobClientLiveTest {
public void testListOwnedContainers() throws Exception {
// Test default listing
SortedSet<ListableContainerProperties> response = connection.listContainers();
SortedSet<ListableContainerProperties> response = connection.listContainers().get(10,
TimeUnit.SECONDS);
// assertEquals(response.size(), initialContainerCount + 2);// if the containers already
// exist, this will fail
// Test listing with options
response = connection.listContainers(ListOptions.Builder.prefix(
privateContainer.substring(0, privateContainer.length() - 1)).maxResults(1));
response = connection
.listContainers(
ListOptions.Builder.prefix(
privateContainer.substring(0, privateContainer.length() - 1))
.maxResults(1)).get(10, TimeUnit.SECONDS);
assertEquals(response.size(), 1);
assertEquals(response.first().getName(), privateContainer);
response = connection.listContainers(ListOptions.Builder.prefix(publicContainer)
.maxResults(1));
response = connection.listContainers(
ListOptions.Builder.prefix(publicContainer).maxResults(1)).get(10, TimeUnit.SECONDS);
assertEquals(response.size(), 1);
assertEquals(response.first().getName(), publicContainer);
@ -273,7 +280,7 @@ public class AzureBlobClientLiveTest {
// Multimap<String, String> userMetadata = HashMultimap.create();
// userMetadata.put("New-Metadata-1", "value-1");
// userMetadata.put("New-Metadata-2", "value-2");
// assertTrue(connection.setObjectMetadata(privateContainer, object.getProperties().getName(),
// assertTrue(connection.setBlobProperties(privateContainer, object.getProperties().getName(),
// userMetadata));
// Test GET of missing object

View File

@ -0,0 +1,110 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.azure.storage.blob.blobstore.config.AzureBlobStoreContextModule;
import org.jclouds.azure.storage.blob.config.AzureBlobRestClientModule;
import org.jclouds.azure.storage.blob.config.AzureBlobStubClientModule;
import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.azure.storage.blob.domain.internal.AzureBlobImpl;
import org.jclouds.azure.storage.blob.internal.StubAzureBlobClient;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.internal.BlobImpl;
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
import org.testng.annotations.Test;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of modules configured in AzureBlobContextBuilder
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "azureblob.AzureBlobContextBuilderTest")
public class AzureBlobStoreContextBuilderTest {
public void testNewBuilder() {
AzureBlobStoreContextBuilder builder = newBuilder();
assertEquals(builder.getProperties().getProperty(PROPERTY_USER_METADATA_PREFIX),
"x-ms-meta-");
assertEquals(builder.getProperties().getProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT),
"id");
assertEquals(builder.getProperties().getProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY),
"secret");
}
private AzureBlobStoreContextBuilder newBuilder() {
return new AzureBlobStoreContextBuilder(new AzureBlobStorePropertiesBuilder("id",
"secret").build()).withModules(new AzureBlobStubClientModule());
}
public void testBuildContext() {
BlobStoreContext<AzureBlobClient> context = newBuilder().buildContext();
assertEquals(context.getClass(), BlobStoreContextImpl.class);
assertEquals(context.getApi().getClass(), StubAzureBlobClient.class);
assertEquals(context.getBlobStore().getClass(), AzureBlobStore.class);
assertEquals(context.getApi().newBlob().getClass(), AzureBlobImpl.class);
assertEquals(context.getBlobStore().newBlob().getClass(), BlobImpl.class);
assertEquals(context.getAccount(), "id");
assertEquals(context.getEndPoint(), URI.create("https://localhost/azurestub"));
}
public void testBuildInjector() {
Injector i = newBuilder().buildInjector();
assert i.getInstance(Key.get(new TypeLiteral<BlobStoreContext<AzureBlobClient>>() {
})) != null;
assert i.getInstance(AzureBlob.class) != null;
assert i.getInstance(Blob.class) != null;
}
protected void testAddContextModule() {
List<Module> modules = new ArrayList<Module>();
AzureBlobStoreContextBuilder builder = newBuilder();
builder.addContextModule(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), AzureBlobStoreContextModule.class);
}
protected void addClientModule() {
List<Module> modules = new ArrayList<Module>();
AzureBlobStoreContextBuilder builder = newBuilder();
builder.addClientModule(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), AzureBlobRestClientModule.class);
}
}

View File

@ -0,0 +1,87 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.config;
import static org.testng.Assert.assertEquals;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.azure.storage.blob.blobstore.strategy.FindMD5InBlobProperties;
import org.jclouds.azure.storage.blob.config.AzureBlobStubClientModule;
import org.jclouds.azure.storage.blob.reference.AzureBlobConstants;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.util.Jsr330;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "azureblob.AzureBlobStoreModuleTest")
public class AzureBlobStoreModuleTest {
Injector createInjector() {
return Guice.createInjector(new ExecutorServiceModule(new WithinThreadExecutorService()),
new JDKLoggingModule(), new AzureBlobStubClientModule(),
new AzureBlobStoreContextModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT))
.to("user");
bindConstant().annotatedWith(
Jsr330.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY)).to(
"key");
bindConstant().annotatedWith(
Jsr330.named(AzureBlobConstants.PROPERTY_AZUREBLOB_ENDPOINT)).to(
"http://localhost");
super.configure();
}
});
}
@Test
void testContextImpl() {
Injector injector = createInjector();
BlobStoreContext<AzureBlobClient> handler = injector.getInstance(Key
.get(new TypeLiteral<BlobStoreContext<AzureBlobClient>>() {
}));
assertEquals(handler.getClass(), BlobStoreContextImpl.class);
ContainsValueInListStrategy valueList = injector
.getInstance(ContainsValueInListStrategy.class);
assertEquals(valueList.getClass(), FindMD5InBlobProperties.class);
}
}

View File

@ -0,0 +1,37 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.integration;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.blobstore.integration.internal.BaseContainerIntegrationTest;
import org.testng.annotations.Test;
/**
* @author James Murty
* @author Adrian Cole
*/
@Test(groups = { "integration", "live" }, testName = "azureblob.AzureBlobContainerIntegrationTest")
public class AzureBlobContainerIntegrationTest extends BaseContainerIntegrationTest<AzureBlobClient> {
}

View File

@ -0,0 +1,36 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.integration;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.blobstore.integration.internal.BaseContainerLiveTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = { "live" }, testName = "azureblob.AzureBlobContainerLiveTest")
public class AzureBlobContainerLiveTest extends BaseContainerLiveTest<AzureBlobClient> {
}

View File

@ -0,0 +1,37 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.integration;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.blobstore.integration.internal.BaseInputStreamMapIntegrationTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = { "integration", "live" }, testName = "azureblob.AzureBlobInputStreamMapIntegrationTest")
public class AzureBlobInputStreamMapIntegrationTest extends
BaseInputStreamMapIntegrationTest<AzureBlobClient> {
}

View File

@ -0,0 +1,37 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.integration;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.blobstore.integration.internal.BaseBlobIntegrationTest;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = { "integration", "live" }, testName = "azureblob.AzureBlobIntegrationTest")
public class AzureBlobIntegrationTest extends BaseBlobIntegrationTest<AzureBlobClient> {
}

View File

@ -0,0 +1,37 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.integration;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.blobstore.integration.internal.BaseBlobLiveTest;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = { "live" }, testName = "azureblob.AzureBlobLiveTest")
public class AzureBlobLiveTest extends BaseBlobLiveTest<AzureBlobClient> {
}

View File

@ -0,0 +1,36 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.integration;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.blobstore.integration.internal.BaseBlobMapIntegrationTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = { "integration", "live" }, testName = "azureblob.AzureBlobMapIntegrationTest")
public class AzureBlobMapIntegrationTest extends BaseBlobMapIntegrationTest<AzureBlobClient> {
}

View File

@ -0,0 +1,36 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.integration;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.blobstore.integration.internal.BaseServiceIntegrationTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = { "integration", "live" }, testName = "azureblob.AzureBlobServiceIntegrationTest")
public class AzureBlobServiceIntegrationTest extends BaseServiceIntegrationTest<AzureBlobClient> {
}

View File

@ -0,0 +1,57 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.blobstore.integration;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStoreContextBuilder;
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStoreContextFactory;
import org.jclouds.azure.storage.blob.blobstore.AzureBlobStorePropertiesBuilder;
import org.jclouds.azure.storage.blob.config.AzureBlobStubClientModule;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.integration.internal.BaseTestInitializer;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
public class AzureBlobTestInitializer extends BaseTestInitializer<AzureBlobClient> {
@Override
protected BlobStoreContext<AzureBlobClient> createLiveContext(Module configurationModule,
String url, String app, String account, String key) {
return new AzureBlobStoreContextBuilder(new AzureBlobStorePropertiesBuilder(
account, key).relaxSSLHostname().build()).withModules(configurationModule,
new Log4JLoggingModule()).buildContext();
}
@Override
protected BlobStoreContext<AzureBlobClient> createStubContext() {
return AzureBlobStoreContextFactory.createContext("user", "pass",
new AzureBlobStubClientModule());
}
}

View File

@ -21,13 +21,13 @@
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob;
package org.jclouds.azure.storage.blob.config;
import static org.testng.Assert.assertEquals;
import org.jclouds.azure.storage.blob.config.AzureBlobContextModule;
import org.jclouds.azure.storage.blob.config.AzureBlobStubClientModule;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.azure.storage.blob.reference.AzureBlobConstants;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.RestContextImpl;
import org.jclouds.util.Jsr330;
@ -45,27 +45,28 @@ import com.google.inject.TypeLiteral;
public class AzureBlobContextModuleTest {
Injector createInjector() {
return Guice.createInjector(new AzureBlobStubClientModule(), new AzureBlobContextModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Jsr330.named(AzureBlobConstants.PROPERTY_AZURESTORAGE_ACCOUNT)).to("user");
bindConstant()
.annotatedWith(Jsr330.named(AzureBlobConstants.PROPERTY_AZURESTORAGE_KEY)).to(
"key");
bindConstant().annotatedWith(
Jsr330.named(AzureBlobConstants.PROPERTY_AZUREBLOB_ENDPOINT)).to(
"http://localhost");
super.configure();
}
});
return Guice.createInjector(new AzureBlobStubClientModule(), new JDKLoggingModule(),
new AzureBlobContextModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Jsr330.named(AzureBlobConstants.PROPERTY_AZURESTORAGE_ACCOUNT)).to(
"user");
bindConstant().annotatedWith(
Jsr330.named(AzureBlobConstants.PROPERTY_AZURESTORAGE_KEY)).to("key");
bindConstant().annotatedWith(
Jsr330.named(AzureBlobConstants.PROPERTY_AZUREBLOB_ENDPOINT)).to(
"http://localhost");
super.configure();
}
});
}
@Test
void testContextImpl() {
RestContext<AzureBlobClient> handler = createInjector().getInstance(
Key.get(new TypeLiteral<RestContext<AzureBlobClient>>() {
Injector injector = createInjector();
RestContext<AzureBlobClient> handler = injector.getInstance(Key
.get(new TypeLiteral<RestContext<AzureBlobClient>>() {
}));
assertEquals(handler.getClass(), RestContextImpl.class);

View File

@ -1,20 +1,44 @@
package org.jclouds.azure.storage.blob.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import javax.inject.Inject;
import org.jclouds.azure.storage.blob.AzureBlobClient;
import org.jclouds.azure.storage.blob.blobstore.functions.AzureBlobToBlob;
import org.jclouds.azure.storage.blob.blobstore.functions.BlobMetadataToBlobProperties;
import org.jclouds.azure.storage.blob.blobstore.functions.BlobToAzureBlob;
import org.jclouds.azure.storage.blob.blobstore.functions.ListBlobsOptionsToListOptions;
import org.jclouds.azure.storage.blob.blobstore.functions.ResourceToListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.AzureBlob;
import org.jclouds.azure.storage.blob.domain.BlobProperties;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableContainerProperties;
import org.jclouds.azure.storage.blob.domain.internal.ListableContainerPropertiesImpl;
import org.jclouds.azure.storage.blob.options.CreateContainerOptions;
import org.jclouds.azure.storage.blob.options.ListBlobsOptions;
import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.internal.BoundedTreeSet;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.attr.ConsistencyModels;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions;
import org.jclouds.blobstore.integration.internal.StubBlobStore;
import org.jclouds.blobstore.integration.internal.StubBlobStore.FutureBase;
import org.jclouds.concurrent.FutureFunctionWrapper;
import org.jclouds.http.options.GetOptions;
import org.jclouds.logging.Logger.LoggerFactory;
import org.joda.time.DateTime;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
/**
* Implementation of {@link AzureBlobClient} which keeps all data in a local Map object.
@ -23,9 +47,45 @@ import org.jclouds.http.options.GetOptions;
*/
@ConsistencyModel(ConsistencyModels.STRICT)
public class StubAzureBlobClient implements AzureBlobClient {
private final HttpGetOptionsListToGetOptions httpGetOptionsConverter;
private final StubBlobStore blobStore;
private final LoggerFactory logFactory;
private final AzureBlob.Factory objectProvider;
private final AzureBlobToBlob object2Blob;
private final BlobToAzureBlob blob2Object;
private final BlobMetadataToBlobProperties blob2ObjectInfo;
private final ListBlobsOptionsToListOptions container2ContainerListOptions;
private final ResourceToListBlobsResponse resource2ObjectList;
private final ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs;
@Inject
private StubAzureBlobClient(StubBlobStore blobStore, LoggerFactory logFactory,
ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
AzureBlob.Factory objectProvider,
HttpGetOptionsListToGetOptions httpGetOptionsConverter, AzureBlobToBlob object2Blob,
BlobToAzureBlob blob2Object, BlobMetadataToBlobProperties blob2ObjectInfo,
ListBlobsOptionsToListOptions container2ContainerListOptions,
ResourceToListBlobsResponse resource2ContainerList) {
this.logFactory = logFactory;
this.containerToBlobs = containerToBlobs;
this.blobStore = blobStore;
this.objectProvider = objectProvider;
this.httpGetOptionsConverter = httpGetOptionsConverter;
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
this.blob2ObjectInfo = checkNotNull(blob2ObjectInfo, "blob2ObjectInfo");
this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions,
"container2ContainerListOptions");
this.resource2ObjectList = checkNotNull(resource2ContainerList, "resource2ContainerList");
}
protected <F, T> Future<T> wrapFuture(Future<? extends F> future, Function<F, T> function) {
return new FutureFunctionWrapper<F, T>(future, function, logFactory.getLogger(function
.getClass().getName()));
}
public Future<Boolean> createContainer(String container, CreateContainerOptions... options) {
throw new UnsupportedOperationException();
return blobStore.createContainer(container);
}
public Future<Boolean> createRootContainer(CreateContainerOptions... options) {
@ -33,11 +93,16 @@ public class StubAzureBlobClient implements AzureBlobClient {
}
public Future<Void> deleteBlob(String container, String key) {
throw new UnsupportedOperationException();
return blobStore.removeBlob(container, key);
}
public Future<Void> deleteContainer(String container) {
throw new UnsupportedOperationException();
public Future<Void> deleteContainer(final String container) {
return new FutureBase<Void>() {
public Void get() throws InterruptedException, ExecutionException {
StubAzureBlobClient.this.containerToBlobs.remove(container);
return null;
}
};
}
public Future<Boolean> deleteRootContainer() {
@ -45,35 +110,53 @@ public class StubAzureBlobClient implements AzureBlobClient {
}
public Future<AzureBlob> getBlob(String container, String key, GetOptions... options) {
throw new UnsupportedOperationException();
org.jclouds.blobstore.options.GetOptions getOptions = httpGetOptionsConverter.apply(options);
return wrapFuture(blobStore.getBlob(container, key, getOptions), blob2Object);
}
public BlobProperties getBlobProperties(String container, String key) {
throw new UnsupportedOperationException();
return blob2ObjectInfo.apply(blobStore.blobMetadata(container, key));
}
public ListableContainerProperties getContainerProperties(String container) {
throw new UnsupportedOperationException();
}
public Future<ListBlobsResponse> listBlobs(String container, ListBlobsOptions... options) {
throw new UnsupportedOperationException();
public Future<ListBlobsResponse> listBlobs(String container, ListBlobsOptions... optionsList) {
org.jclouds.blobstore.options.ListOptions options = container2ContainerListOptions
.apply(optionsList);
return wrapFuture(blobStore.list(container, options), resource2ObjectList);
}
public Future<ListBlobsResponse> listBlobs(ListBlobsOptions... options) {
throw new UnsupportedOperationException();
}
public BoundedList<ListableContainerProperties> listContainers(ListOptions... listOptions) {
throw new UnsupportedOperationException();
public Future<? extends BoundedSortedSet<ListableContainerProperties>> listContainers(
ListOptions... listOptions) {
return new FutureBase<BoundedSortedSet<ListableContainerProperties>>() {
public BoundedSortedSet<ListableContainerProperties> get() throws InterruptedException,
ExecutionException {
return new BoundedTreeSet<ListableContainerProperties>(Iterables.transform(blobStore
.getContainerToBlobs().keySet(),
new Function<String, ListableContainerProperties>() {
public ListableContainerProperties apply(String name) {
return new ListableContainerPropertiesImpl(URI.create("http://stub/"
+ name), new DateTime(), "");
}
}), null, null, null, null, null);
}
};
}
public AzureBlob newBlob() {
throw new UnsupportedOperationException();
return objectProvider.create(null);
}
public Future<String> putBlob(String container, AzureBlob object) {
throw new UnsupportedOperationException();
return blobStore.putBlob(container, object2Blob.apply(object));
}
public void setBlobMetadata(String container, String key, Map<String, String> metadata) {
@ -84,4 +167,8 @@ public class StubAzureBlobClient implements AzureBlobClient {
throw new UnsupportedOperationException();
}
public boolean containerExists(String container) {
return blobStore.getContainerToBlobs().containsKey(container);
}
}

View File

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

View File

@ -31,7 +31,7 @@ import java.util.SortedSet;
* @author Adrian Cole
*
*/
public interface BoundedList<T> extends SortedSet<T> {
public interface BoundedSortedSet<T> extends SortedSet<T> {
URI getUrl();
String getPrefix();

View File

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

View File

@ -45,6 +45,10 @@ public class ListOptions extends BaseHttpRequestOptions {
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
@ -58,6 +62,10 @@ public class ListOptions extends BaseHttpRequestOptions {
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,
@ -70,6 +78,11 @@ public class ListOptions extends BaseHttpRequestOptions {
return this;
}
public Integer getMaxResults() {
String maxresults = getFirstQueryOrNull("maxresults");
return (maxresults != null) ? new Integer(maxresults) : null;
}
public static class Builder {
/**

View File

@ -33,7 +33,7 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import org.jclouds.azure.storage.AzureQueue;
import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
import org.jclouds.azure.storage.options.CreateOptions;
import org.jclouds.azure.storage.options.ListOptions;
@ -85,7 +85,7 @@ public interface AzureQueueClient {
@XMLResponseParser(AccountNameEnumerationResultsHandler.class)
@Path("/")
@QueryParams(keys = "comp", values = "list")
BoundedList<QueueMetadata> listQueues(ListOptions... listOptions);
BoundedSortedSet<QueueMetadata> listQueues(ListOptions... listOptions);
/**
* The Create Queue operation creates a new queue under the specified account.

View File

@ -29,7 +29,7 @@ import java.util.TreeSet;
import javax.inject.Inject;
import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.domain.internal.BoundedTreeSet;
import org.jclouds.azure.storage.queue.domain.QueueMetadata;
import org.jclouds.http.functions.ParseSax;
@ -43,7 +43,7 @@ import org.jclouds.http.functions.ParseSax;
* @author Adrian Cole
*/
public class AccountNameEnumerationResultsHandler extends
ParseSax.HandlerWithResult<BoundedList<QueueMetadata>> {
ParseSax.HandlerWithResult<BoundedSortedSet<QueueMetadata>> {
private SortedSet<QueueMetadata> metadata = new TreeSet<QueueMetadata>();
private URI currentUrl;
@ -59,7 +59,7 @@ public class AccountNameEnumerationResultsHandler extends
public AccountNameEnumerationResultsHandler() {
}
public BoundedList<QueueMetadata> getResult() {
public BoundedSortedSet<QueueMetadata> getResult() {
return new BoundedTreeSet<QueueMetadata>(metadata, currentUrl, prefix, marker, maxResults,
nextMarker);
}

View File

@ -29,7 +29,7 @@ import static org.testng.Assert.assertTrue;
import java.lang.reflect.UndeclaredThrowableException;
import java.security.SecureRandom;
import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.azure.storage.domain.BoundedSortedSet;
import org.jclouds.azure.storage.options.CreateOptions;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.queue.domain.QueueMetadata;
@ -67,7 +67,7 @@ public class AzureQueueClientLiveTest {
@Test
public void testListQueues() throws Exception {
BoundedList<QueueMetadata> response = connection.listQueues();
BoundedSortedSet<QueueMetadata> response = connection.listQueues();
assert null != response;
long initialQueueCount = response.size();
assertTrue(initialQueueCount >= 0);
@ -93,7 +93,7 @@ public class AzureQueueClientLiveTest {
throw e;
}
}
BoundedList<QueueMetadata> response = connection.listQueues();
BoundedSortedSet<QueueMetadata> response = connection.listQueues();
assert null != response;
long queueCount = response.size();
assertTrue(queueCount >= 1);
@ -103,7 +103,7 @@ public class AzureQueueClientLiveTest {
@Test
public void testListQueuesWithOptions() throws Exception {
BoundedList<QueueMetadata> response = connection.listQueues(ListOptions.Builder.prefix(
BoundedSortedSet<QueueMetadata> response = connection.listQueues(ListOptions.Builder.prefix(
privateQueue).maxResults(1));
assert null != response;
long initialQueueCount = response.size();

View File

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