Issue 86: first command for blob service

git-svn-id: http://jclouds.googlecode.com/svn/trunk@1876 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-09-03 04:26:39 +00:00
parent 36aadce94f
commit 7e9229d55e
16 changed files with 932 additions and 0 deletions

View File

@ -0,0 +1,70 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import org.jclouds.azure.storage.blob.domain.ContainerMetadataList;
import org.jclouds.azure.storage.blob.xml.AccountNameEnumerationResultsHandler;
import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.reference.AzureStorageHeaders;
import org.jclouds.rest.Header;
import org.jclouds.rest.Query;
import org.jclouds.rest.RequestFilters;
import org.jclouds.rest.SkipEncoding;
import org.jclouds.rest.XMLResponseParser;
/**
* 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 wrapped in an {@link ExecutionException} as documented in {@link Future#get()}.
*
* @see <a href="http://msdn.microsoft.com/en-us/library/dd135733.aspx" />
* @author Adrian Cole
*/
@SkipEncoding('/')
@RequestFilters(SharedKeyAuthentication.class)
@Header(key = AzureStorageHeaders.VERSION, value = "2009-07-17")
public interface AzureBlobConnection {
/**
* The List Containers operation returns a list of the containers under the specified account.
*
* @param listOptions
* controls the number or type of results requested
* @see ListOptions
*/
@GET
@XMLResponseParser(AccountNameEnumerationResultsHandler.class)
@Path("/")
@Query(key = "comp", value = "list")
ContainerMetadataList listContainers(ListOptions... listOptions);
}

View File

@ -0,0 +1,16 @@
package org.jclouds.azure.storage.blob;
import org.jclouds.cloud.CloudContext;
/**
* Represents an authenticated context to Cloud Files.
*
* @see <a href="http://www.rackspacecloud.com/cf-devguide-20090311.pdf" />
* @see AzureBlobConnection
* @see CloudContext
* @author Adrian Cole
*
*/
public interface AzureBlobContext extends CloudContext<AzureBlobConnection> {
}

View File

@ -0,0 +1,114 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_ADDRESS;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_REDIRECTS;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_RETRIES;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_SECURE;
import static org.jclouds.http.HttpConstants.PROPERTY_SAX_DEBUG;
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_IO_WORKER_THREADS;
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS;
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE;
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES;
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_REQUEST_INVOKER_THREADS;
import java.util.List;
import java.util.Properties;
import org.jclouds.azure.storage.blob.config.AzureBlobContextModule;
import org.jclouds.azure.storage.blob.config.RestAzureBlobConnectionModule;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.azure.storage.xml.config.AzureStorageParserModule;
import org.jclouds.cloud.CloudContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
* Creates {@link AzureBlobContext} 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
* @see AzureBlobContext
*/
public class AzureBlobContextBuilder extends
CloudContextBuilder<AzureBlobConnection, AzureBlobContext> {
public AzureBlobContextBuilder(Properties props) {
super(props);
}
public static AzureBlobContextBuilder newBuilder(String id, String secret) {
Properties properties = new Properties();
properties.setProperty(PROPERTY_HTTP_ADDRESS, id + ".blob.core.windows.net");
properties.setProperty(PROPERTY_HTTP_SECURE, "true");
properties.setProperty(PROPERTY_SAX_DEBUG, "false");
properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, "5");
properties.setProperty(PROPERTY_HTTP_MAX_REDIRECTS, "5");
properties.setProperty(PROPERTY_POOL_MAX_CONNECTION_REUSE, "75");
properties.setProperty(PROPERTY_POOL_MAX_SESSION_FAILURES, "2");
properties.setProperty(PROPERTY_POOL_REQUEST_INVOKER_THREADS, "1");
properties.setProperty(PROPERTY_POOL_IO_WORKER_THREADS, "2");
properties.setProperty(PROPERTY_POOL_MAX_CONNECTIONS, "12");
AzureBlobContextBuilder builder = new AzureBlobContextBuilder(properties);
builder.authenticate(id, secret);
return builder;
}
public void authenticate(String id, String secret) {
properties.setProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT, checkNotNull(id,
"azureStorageAccount"));
properties.setProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY, checkNotNull(secret,
"azureStorageKey"));
}
public AzureBlobContext buildContext() {
return buildInjector().getInstance(AzureBlobContext.class);
}
protected void addParserModule(List<Module> modules) {
modules.add(new AzureStorageParserModule());
}
protected void addContextModule(List<Module> modules) {
modules.add(new AzureBlobContextModule());
}
protected void addConnectionModule(List<Module> modules) {
modules.add(new RestAzureBlobConnectionModule());
}
}

View File

@ -0,0 +1,22 @@
package org.jclouds.azure.storage.blob.config;
import org.jclouds.azure.storage.blob.AzureBlobConnection;
import org.jclouds.azure.storage.blob.AzureBlobContext;
import org.jclouds.azure.storage.blob.internal.GuiceAzureBlobContext;
import com.google.inject.AbstractModule;
/**
* Configures the {@link AzureBlobContext}; requires {@link AzureBlobConnection} bound.
*
* @author Adrian Cole
*/
public class AzureBlobContextModule extends AbstractModule {
@Override
protected void configure() {
this.requireBinding(AzureBlobConnection.class);
bind(AzureBlobContext.class).to(GuiceAzureBlobContext.class);
}
}

View File

@ -0,0 +1,29 @@
package org.jclouds.azure.storage.blob.config;
import java.net.URI;
import org.jclouds.azure.storage.blob.AzureBlobConnection;
import org.jclouds.azure.storage.config.RestAzureStorageConnectionModule;
import org.jclouds.cloud.ConfiguresCloudConnection;
import org.jclouds.http.RequiresHttp;
import org.jclouds.rest.RestClientFactory;
import com.google.inject.Provides;
import com.google.inject.Singleton;
/**
* Configures the Azure Blob Service connection, including logging and http transport.
*
* @author Adrian Cole
*/
@ConfiguresCloudConnection
@RequiresHttp
public class RestAzureBlobConnectionModule extends RestAzureStorageConnectionModule {
@Provides
@Singleton
protected AzureBlobConnection provideAzureStorageConnection(URI uri, RestClientFactory factory) {
return factory.create(uri, AzureBlobConnection.class);
}
}

View File

@ -0,0 +1,99 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.domain;
import java.net.URI;
import java.util.Arrays;
import org.joda.time.DateTime;
/**
*
* @author Adrian Cole
*
*/
public class ContainerMetadata {
private URI url;
private DateTime lastModified;
private byte[] eTag;
@Override
public String toString() {
return "ContainerMetadata [eTag=" + Arrays.toString(eTag) + ", lastModified=" + lastModified
+ ", url=" + url + "]";
}
public ContainerMetadata(URI url, DateTime lastModified, byte[] eTag) {
this.url = url;
this.lastModified = lastModified;
this.eTag = eTag;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(eTag);
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + ((url == null) ? 0 : url.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ContainerMetadata other = (ContainerMetadata) obj;
if (!Arrays.equals(eTag, other.eTag))
return false;
if (lastModified == null) {
if (other.lastModified != null)
return false;
} else if (!lastModified.equals(other.lastModified))
return false;
if (url == null) {
if (other.url != null)
return false;
} else if (!url.equals(other.url))
return false;
return true;
}
public URI getUrl() {
return url;
}
public DateTime getLastModified() {
return lastModified;
}
public byte[] getETag() {
return eTag;
}
}

View File

@ -0,0 +1,97 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.domain;
import java.util.List;
/**
*
* @author Adrian Cole
*
*/
public class ContainerMetadataList {
private int maxResults;
private List<ContainerMetadata> containerMetadata;
private String nextMarker;
public ContainerMetadataList(int maxResults, List<ContainerMetadata> containerMetadata,
String nextMarker) {
this.maxResults = maxResults;
this.containerMetadata = containerMetadata;
this.nextMarker = nextMarker;
}
public int getMaxResults() {
return maxResults;
}
public List<ContainerMetadata> getContainerMetadata() {
return containerMetadata;
}
public String getNextMarker() {
return nextMarker;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((containerMetadata == null) ? 0 : containerMetadata.hashCode());
result = prime * result + maxResults;
result = prime * result + ((nextMarker == null) ? 0 : nextMarker.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ContainerMetadataList other = (ContainerMetadataList) obj;
if (containerMetadata == null) {
if (other.containerMetadata != null)
return false;
} else if (!containerMetadata.equals(other.containerMetadata))
return false;
if (maxResults != other.maxResults)
return false;
if (nextMarker == null) {
if (other.nextMarker != null)
return false;
} else if (!nextMarker.equals(other.nextMarker))
return false;
return true;
}
@Override
public String toString() {
return "ContainerMetadataList [containerMetadata=" + containerMetadata + ", maxResults="
+ maxResults + ", nextMarker=" + nextMarker + "]";
}
}

View File

@ -0,0 +1,55 @@
package org.jclouds.azure.storage.blob.internal;
import java.io.IOException;
import javax.annotation.Resource;
import org.jclouds.azure.storage.blob.AzureBlobConnection;
import org.jclouds.azure.storage.blob.AzureBlobContext;
import org.jclouds.lifecycle.Closer;
import org.jclouds.logging.Logger;
import com.google.inject.Inject;
import com.google.inject.Injector;
/**
* Uses a Guice Injector to configure the objects served by AzureBlobContext methods.
*
* @author Adrian Cole
* @see Injector
*/
public class GuiceAzureBlobContext implements AzureBlobContext {
@Resource
private Logger logger = Logger.NULL;
private final Injector injector;
private final Closer closer;
@Inject
private GuiceAzureBlobContext(Injector injector, Closer closer) {
this.injector = injector;
this.closer = closer;
}
/**
* {@inheritDoc}
*/
public AzureBlobConnection getConnection() {
return injector.getInstance(AzureBlobConnection.class);
}
/**
* {@inheritDoc}
*
* @see Closer
*/
public void close() {
try {
closer.close();
} catch (IOException e) {
logger.error(e, "error closing content");
}
}
}

View File

@ -0,0 +1,93 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.xml;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.jclouds.azure.storage.blob.domain.ContainerMetadata;
import org.jclouds.azure.storage.blob.domain.ContainerMetadataList;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.DateService;
import org.joda.time.DateTime;
import com.google.inject.Inject;
/**
* Parses the following XML document:
* <p/>
* EnumerationResults AccountName="http://myaccount.blob.core.windows.net"
*
* @see <a href="http://msdn.microsoft.com/en-us/library/dd179352.aspx" />
* @author Adrian Cole
*/
public class AccountNameEnumerationResultsHandler extends
ParseSax.HandlerWithResult<ContainerMetadataList> {
private List<ContainerMetadata> containers = new ArrayList<ContainerMetadata>();
private int maxResults;
private String nextMarker;
private URI currentUrl;
private DateTime currentLastModified;
private byte[] currentETag;
private StringBuilder currentText = new StringBuilder();
private final DateService dateParser;
@Inject
public AccountNameEnumerationResultsHandler(DateService dateParser) {
this.dateParser = dateParser;
}
public ContainerMetadataList getResult() {
return new ContainerMetadataList(maxResults, containers, nextMarker);
}
public void endElement(String uri, String name, String qName) {
if (qName.equals("MaxResults")) {
maxResults = Integer.parseInt(currentText.toString().trim());
} else if (qName.equals("NextMarker")) {
nextMarker = currentText.toString().trim();
} else if (qName.equals("Container")) {
containers.add(new ContainerMetadata(currentUrl, currentLastModified, currentETag));
currentUrl = null;
currentLastModified = null;
currentETag = null;
} else if (qName.equals("Url")) {
currentUrl = URI.create(currentText.toString().trim());
} else if (qName.equals("LastModified")) {
currentLastModified = dateParser.rfc822DateParse(currentText.toString().trim());
} else if (qName.equals("Etag")) {
currentETag = HttpUtils.fromHexString(currentText.toString().trim());
}
currentText = new StringBuilder();
}
public void characters(char ch[], int start, int length) {
currentText.append(ch, start, length);
}
}

View File

@ -0,0 +1,28 @@
package org.jclouds.azure.storage.blob.xml;
import org.jclouds.azure.storage.blob.domain.ContainerMetadataList;
import org.jclouds.azure.storage.xml.AzureStorageParserFactory;
import org.jclouds.http.functions.ParseSax;
import com.google.inject.Inject;
import com.google.inject.Provider;
/**
* Creates Parsers needed to interpret Azure Blob Service messages. This class uses guice assisted
* inject, which mandates the creation of many single-method interfaces. These interfaces are not
* intended for public api.
*
* @author Adrian Cole
*/
public class AzureBlobParserFactory extends AzureStorageParserFactory {
@Inject
private GenericParseFactory<ContainerMetadataList> parseContainerMetadataListFactory;
@Inject
Provider<AccountNameEnumerationResultsHandler> containerMetaListHandlerProvider;
public ParseSax<ContainerMetadataList> createContainerMetadataListParser() {
return parseContainerMetadataListFactory.create(containerMetaListHandlerProvider.get());
}
}

View File

@ -0,0 +1,39 @@
package org.jclouds.azure.storage.blob.xml.config;
import org.jclouds.azure.storage.blob.domain.ContainerMetadataList;
import org.jclouds.azure.storage.blob.xml.AccountNameEnumerationResultsHandler;
import org.jclouds.azure.storage.xml.AzureStorageParserFactory;
import org.jclouds.azure.storage.xml.config.AzureStorageParserModule;
import org.jclouds.command.ConfiguresResponseTransformer;
import org.jclouds.http.functions.ParseSax;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryProvider;
/**
* Creates the factories needed to interpret Azure Blob Service responses
*
* @author Adrian Cole
*/
@ConfiguresResponseTransformer
public class AzureBlobParserModule extends AzureStorageParserModule {
protected final TypeLiteral<AzureStorageParserFactory.GenericParseFactory<ContainerMetadataList>> accountNameEnumerationResultsHandler = new TypeLiteral<AzureStorageParserFactory.GenericParseFactory<ContainerMetadataList>>() {
};
@Override
protected void bindParserImplementationsToReturnTypes() {
super.bindParserImplementationsToReturnTypes();
bind(new TypeLiteral<ParseSax.HandlerWithResult<ContainerMetadataList>>() {
}).to(AccountNameEnumerationResultsHandler.class);
}
@Override
protected void bindCallablesThatReturnParseResults() {
super.bindCallablesThatReturnParseResults();
bind(accountNameEnumerationResultsHandler).toProvider(
FactoryProvider.newFactory(accountNameEnumerationResultsHandler,
new TypeLiteral<ParseSax<ContainerMetadataList>>() {
}));
}
}

View File

@ -0,0 +1,45 @@
package org.jclouds.azure.storage.blob;
import static org.testng.Assert.assertTrue;
import org.jclouds.azure.storage.blob.domain.ContainerMetadataList;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.inject.Injector;
/**
* Tests behavior of {@code AzureBlobConnection}
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true, testName = "cloudservers.AzureBlobConnectionLiveTest")
public class AzureBlobConnectionLiveTest {
protected static final String sysAzureStorageAccount = System
.getProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT);
protected static final String sysAzureStorageKey = System
.getProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY);
protected AzureBlobConnection connection;
@BeforeGroups(groups = { "live" })
public void setupConnection() {
Injector injector = AzureBlobContextBuilder.newBuilder(sysAzureStorageAccount,
sysAzureStorageKey).withModules(new Log4JLoggingModule()).withSaxDebug()
.buildInjector();
connection = injector.getInstance(AzureBlobConnection.class);
}
@Test
public void testListContainers() throws Exception {
ContainerMetadataList response = connection.listContainers();
assert null != response;
long initialContainerCount = response.getContainerMetadata().size();
assertTrue(initialContainerCount >= 0);
}
}

View File

@ -0,0 +1,103 @@
package org.jclouds.azure.storage.blob;
import static org.jclouds.azure.storage.options.ListOptions.Builder.maxResults;
import static org.testng.Assert.assertEquals;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Collections;
import javax.ws.rs.HttpMethod;
import org.jclouds.azure.storage.blob.xml.config.AzureBlobParserModule;
import org.jclouds.azure.storage.options.ListOptions;
import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.JaxrsAnnotationProcessor;
import org.jclouds.rest.config.JaxrsModule;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.name.Names;
/**
* Tests behavior of {@code AzureBlobConnection}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "cloudservers.AzureBlobConnectionTest")
public class AzureBlobConnectionTest {
JaxrsAnnotationProcessor.Factory factory;
private static final Class<? extends ListOptions[]> listOptionsVarargsClass = new ListOptions[] {}
.getClass();
public void testListServers() throws SecurityException, NoSuchMethodException {
Method method = AzureBlobConnection.class
.getMethod("listContainers", listOptionsVarargsClass);
URI endpoint = URI.create("http://localhost");
HttpRequest httpMethod = processor.createRequest(endpoint, method, new Object[] {});
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/");
assertEquals(httpMethod.getEndpoint().getQuery(), "comp=list");
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
assertEquals(processor.createResponseParser(method).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null);
}
public void testListServersOptions() throws SecurityException, NoSuchMethodException {
Method method = AzureBlobConnection.class
.getMethod("listContainers", listOptionsVarargsClass);
URI endpoint = URI.create("http://localhost");
HttpRequest httpMethod = processor.createRequest(endpoint, method, new Object[] { maxResults(
1).marker("marker").prefix("prefix") });
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
assertEquals(httpMethod.getEndpoint().getPath(), "/");
assertEquals(httpMethod.getEndpoint().getQuery(),
"comp=list&marker=marker&maxresults=1&prefix=prefix");
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
assertEquals(httpMethod.getHeaders().size(), 1);
assertEquals(httpMethod.getHeaders().get("x-ms-version"), Collections
.singletonList("2009-07-17"));
assertEquals(processor.createResponseParser(method).getClass(), ParseSax.class);
// TODO check generic type of response parser
assertEquals(processor.createExceptionParserOrNullIfNotFound(method), null);
}
JaxrsAnnotationProcessor processor;
@BeforeClass
void setupFactory() {
factory = Guice.createInjector(
new AzureBlobParserModule(),
new AbstractModule() {
@Override
protected void configure() {
bind(URI.class).toInstance(URI.create("http://localhost:8080"));
bindConstant().annotatedWith(
Names.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT)).to(
"user");
bindConstant().annotatedWith(
Names.named(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY)).to(
HttpUtils.toBase64String("key".getBytes()));
}
}, new JaxrsModule(), new ExecutorServiceModule(new WithinThreadExecutorService()),
new JavaUrlHttpCommandExecutorServiceModule()).getInstance(
JaxrsAnnotationProcessor.Factory.class);
processor = factory.create(AzureBlobConnection.class);
}
}

View File

@ -0,0 +1,65 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.azure.storage.blob.xml;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.net.URI;
import org.jclouds.azure.storage.blob.domain.ContainerMetadata;
import org.jclouds.azure.storage.blob.domain.ContainerMetadataList;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
/**
* Tests behavior of {@code ParseFlavorListFromGsonResponseTest}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "azureblob.AccountNameEnumerationResultsHandlerTest")
public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/test_list_containers.xml");
ContainerMetadataList list = new ContainerMetadataList(3, ImmutableList.of(
new ContainerMetadata(URI.create("http://myaccount.blob.core.windows.net/audio"),
dateService.rfc822DateParse("Wed, 13 Aug 2008 20:39:39 GMT"), HttpUtils
.fromHexString("0x8CACB9BD7C6B1B2")), new ContainerMetadata(URI
.create("http://myaccount.blob.core.windows.net/images"), dateService
.rfc822DateParse("Wed, 14 Aug 2008 20:39:39 GMT"), HttpUtils
.fromHexString("0x8CACB9BD7C1EEEC")), new ContainerMetadata(URI
.create("http://myaccount.blob.core.windows.net/textfiles"), dateService
.rfc822DateParse("Wed, 15 Aug 2008 20:39:39 GMT"), HttpUtils
.fromHexString("0x8CACB9BD7BACAC3"))
), "video");
ParseSax<ContainerMetadataList> parser = parserFactory.createContainerMetadataListParser();
ContainerMetadataList result = parser.parse(is);
assertEquals(result, list);
}
}

View File

@ -0,0 +1,35 @@
package org.jclouds.azure.storage.blob.xml;
import org.jclouds.azure.storage.blob.xml.AzureBlobParserFactory;
import org.jclouds.azure.storage.blob.xml.config.AzureBlobParserModule;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.util.DateService;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class BaseHandlerTest {
protected AzureBlobParserFactory parserFactory = null;
protected DateService dateService = null;
private Injector injector;
@BeforeTest
protected void setUpInjector() {
injector = Guice.createInjector(new AzureBlobParserModule(), new ParserModule());
parserFactory = injector.getInstance(AzureBlobParserFactory.class);
dateService = injector.getInstance(DateService.class);
assert parserFactory != null;
}
@AfterTest
protected void tearDownInjector() {
parserFactory = null;
dateService = null;
injector = null;
}
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<EnumerationResults AccountName=" http://myaccount.blob.core.windows.net">
<MaxResults>3</MaxResults>
<Containers>
<Container>
<Url>http://myaccount.blob.core.windows.net/audio</Url>
<LastModified>Wed, 13 Aug 2008 20:39:39 GMT</LastModified>
<Etag>0x8CACB9BD7C6B1B2</Etag>
</Container>
<Container>
<Url>http://myaccount.blob.core.windows.net/images</Url>
<LastModified>Wed, 14 Aug 2008 20:39:39 GMT</LastModified>
<Etag>0x8CACB9BD7C1EEEC</Etag>
</Container>
<Container>
<Url>http://myaccount.blob.core.windows.net/textfiles</Url>
<LastModified>Wed, 15 Aug 2008 20:39:39 GMT</LastModified>
<Etag>0x8CACB9BD7BACAC3</Etag>
</Container>
</Containers>
<NextMarker>video</NextMarker>
</EnumerationResults>