fixed NPE when httpresponseexception is caused by an io exception

This commit is contained in:
Adrian Cole 2010-07-27 17:04:05 -07:00
parent a168683851
commit d884978a98
8 changed files with 100 additions and 106 deletions

View File

@ -18,6 +18,12 @@
*/
package org.jclouds.aws.s3.functions;
import static com.google.common.base.Predicates.equalTo;
import static com.google.common.base.Throwables.getCausalChain;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.size;
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
import static org.jclouds.util.Utils.propagateOrNull;
import java.util.List;
@ -26,11 +32,8 @@ import javax.inject.Singleton;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.http.HttpResponseException;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
/**
*
@ -40,28 +43,21 @@ import com.google.common.collect.Iterables;
public class ReturnTrueOn404OrNotFoundFalseIfNotEmpty implements Function<Exception, Boolean> {
public Boolean apply(Exception from) {
List<Throwable> throwables = Throwables.getCausalChain(from);
List<Throwable> throwables = getCausalChain(from);
Iterable<AWSResponseException> matchingAWSResponseException = Iterables.filter(throwables,
AWSResponseException.class);
if (Iterables.size(matchingAWSResponseException) >= 1) {
if (Iterables.get(matchingAWSResponseException, 0).getError().getCode().equals(
"BucketNotEmpty"))
Iterable<AWSResponseException> matchingAWSResponseException = filter(throwables, AWSResponseException.class);
if (size(matchingAWSResponseException) >= 1 && get(matchingAWSResponseException, 0).getError() != null) {
if (get(matchingAWSResponseException, 0).getError().getCode().equals("BucketNotEmpty"))
return false;
}
Iterable<ContainerNotFoundException> matchingContainerNotFoundException = Iterables.filter(
throwables, ContainerNotFoundException.class);
if (Iterables.size(matchingContainerNotFoundException) >= 1) {
Iterable<ContainerNotFoundException> matchingContainerNotFoundException = filter(throwables,
ContainerNotFoundException.class);
if (size(matchingContainerNotFoundException) >= 1) {
return true;
}
Iterable<HttpResponseException> matchingHttpResponseException = Iterables.filter(throwables,
HttpResponseException.class);
if (Iterables.size(matchingHttpResponseException) >= 1) {
if (Iterables.get(matchingHttpResponseException, 0).getResponse().getStatusCode() == 404)
return true;
}
if (returnValueOnCodeOrNull(from, true, equalTo(404)) != null)
return true;
return Boolean.class.cast(propagateOrNull(from));
}

View File

@ -20,8 +20,12 @@ package org.jclouds.http;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Throwables.getCausalChain;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.size;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newTreeSet;
import static com.google.common.io.ByteStreams.toByteArray;
@ -562,4 +566,13 @@ public class HttpUtils {
"After wiring, the request has neither chunked encoding nor content length: " + request);
}
}
public static <T> T returnValueOnCodeOrNull(Exception from, T value, Predicate<Integer> codePredicate) {
Iterable<HttpResponseException> throwables = filter(getCausalChain(from), HttpResponseException.class);
if (size(throwables) >= 1 && get(throwables, 0).getResponse() != null
&& codePredicate.apply(get(throwables, 0).getResponse().getStatusCode())) {
return value;
}
return null;
}
}

View File

@ -18,12 +18,12 @@
*/
package org.jclouds.http.functions;
import static com.google.common.base.Predicates.equalTo;
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
import static org.jclouds.util.Utils.propagateOrNull;
import javax.inject.Singleton;
import org.jclouds.http.HttpResponseException;
import com.google.common.base.Function;
/**
@ -34,13 +34,8 @@ import com.google.common.base.Function;
public class ReturnFalseOn404 implements Function<Exception, Boolean> {
public Boolean apply(Exception from) {
if (from instanceof HttpResponseException) {
HttpResponseException responseException = (HttpResponseException) from;
if (responseException.getResponse().getStatusCode() == 404) {
return false;
}
}
return Boolean.class.cast(propagateOrNull(from));
Boolean returnVal = returnValueOnCodeOrNull(from, false, equalTo(404));
return returnVal != null ? returnVal : Boolean.class.cast(propagateOrNull(from));
}
}

View File

@ -18,27 +18,20 @@
*/
package org.jclouds.http.functions;
import static com.google.common.base.Predicates.equalTo;
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
import static org.jclouds.util.Utils.propagateOrNull;
import javax.inject.Singleton;
import org.jclouds.http.HttpResponseException;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
@Singleton
public class ReturnTrueOn404 implements Function<Exception, Boolean> {
public Boolean apply(Exception from) {
Iterable<HttpResponseException> throwables = Iterables.filter(
Throwables.getCausalChain(from), HttpResponseException.class);
if (Iterables.size(throwables) >= 1
&& Iterables.get(throwables, 0).getResponse().getStatusCode() == 404) {
return true;
}
return Boolean.class.cast(propagateOrNull(from));
Boolean returnVal = returnValueOnCodeOrNull(from, true, equalTo(404));
return returnVal != null ? returnVal : Boolean.class.cast(propagateOrNull(from));
}
}

View File

@ -67,14 +67,17 @@ import com.google.inject.name.Names;
import com.google.inject.util.Types;
/**
* Creates {@link RestContext} or {@link Injector} instances based on the most commonly requested
* arguments.
* Creates {@link RestContext} 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.
* 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.
* 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 RestContext
@ -95,22 +98,18 @@ public class RestContextBuilder<S, A> {
toBind.putAll(System.getProperties());
Names.bindProperties(binder(), toBind);
bind(String.class).annotatedWith(Provider.class).toInstance(
checkNotNull(toBind.getProperty(PROPERTY_PROVIDER), PROPERTY_PROVIDER));
checkNotNull(toBind.getProperty(PROPERTY_PROVIDER), PROPERTY_PROVIDER));
bind(URI.class).annotatedWith(Provider.class).toInstance(
URI.create(checkNotNull(toBind.getProperty(PROPERTY_ENDPOINT),
PROPERTY_ENDPOINT)));
URI.create(checkNotNull(toBind.getProperty(PROPERTY_ENDPOINT), PROPERTY_ENDPOINT)));
if (toBind.containsKey(PROPERTY_API))
bind(String.class).annotatedWith(Api.class).toInstance(
toBind.getProperty(PROPERTY_API));
bind(String.class).annotatedWith(Api.class).toInstance(toBind.getProperty(PROPERTY_API));
if (toBind.containsKey(PROPERTY_API_VERSION))
bind(String.class).annotatedWith(ApiVersion.class).toInstance(
toBind.getProperty(PROPERTY_API_VERSION));
bind(String.class).annotatedWith(ApiVersion.class).toInstance(toBind.getProperty(PROPERTY_API_VERSION));
if (toBind.containsKey(PROPERTY_IDENTITY))
bind(String.class).annotatedWith(Identity.class).toInstance(
checkNotNull(toBind.getProperty(PROPERTY_IDENTITY), PROPERTY_IDENTITY));
checkNotNull(toBind.getProperty(PROPERTY_IDENTITY), PROPERTY_IDENTITY));
if (toBind.containsKey(PROPERTY_CREDENTIAL))
bind(String.class).annotatedWith(Credential.class).toInstance(
toBind.getProperty(PROPERTY_CREDENTIAL));
bind(String.class).annotatedWith(Credential.class).toInstance(toBind.getProperty(PROPERTY_CREDENTIAL));
}
}
@ -120,8 +119,7 @@ public class RestContextBuilder<S, A> {
protected Class<S> syncClientType;
@Inject
public RestContextBuilder(Class<S> syncClientClass, Class<A> asyncClientClass,
Properties properties) {
public RestContextBuilder(Class<S> syncClientClass, Class<A> asyncClientClass, Properties properties) {
this.asyncClientType = checkNotNull(asyncClientClass, "asyncClientType");
this.syncClientType = checkNotNull(syncClientClass, "syncClientType");
this.properties = checkNotNull(properties, "properties");
@ -184,10 +182,10 @@ public class RestContextBuilder<S, A> {
@Override
protected void configure() {
bind(
(TypeLiteral) TypeLiteral.get(Types.newParameterizedType(RestContext.class,
syncClientType, asyncClientType))).to(
TypeLiteral.get(Types.newParameterizedType(RestContextImpl.class,
syncClientType, asyncClientType))).in(Scopes.SINGLETON);
(TypeLiteral) TypeLiteral.get(Types.newParameterizedType(RestContext.class, syncClientType,
asyncClientType))).to(
TypeLiteral.get(Types.newParameterizedType(RestContextImpl.class, syncClientType, asyncClientType)))
.in(Scopes.SINGLETON);
}
@ -260,9 +258,9 @@ public class RestContextBuilder<S, A> {
}
@SuppressWarnings("unchecked")
public RestContext<S, A> buildContext() {
public <T extends RestContext<S, A>> T buildContext() {
Injector injector = buildInjector();
return (RestContext<S, A>) injector.getInstance(Key.get(Types.newParameterizedType(
RestContext.class, syncClientType, asyncClientType)));
return (T) injector.getInstance(Key.get(Types.newParameterizedType(RestContext.class, syncClientType,
asyncClientType)));
}
}

View File

@ -27,10 +27,10 @@ import javax.inject.Inject;
import org.jclouds.lifecycle.Closer;
import org.jclouds.logging.Logger;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.Utils;
import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.rest.annotations.Provider;
import org.jclouds.rest.Utils;
import com.google.inject.Injector;
import com.google.inject.Key;
@ -55,9 +55,9 @@ public class RestContextImpl<S, A> implements RestContext<S, A> {
private final Utils utils;
@Inject
RestContextImpl(Closer closer, Utils utils, Injector injector, TypeLiteral<S> syncApi,
TypeLiteral<A> asyncApi, @Provider URI endpoint, @Provider String provider,
@Identity String identity, @ApiVersion String apiVersion) {
protected RestContextImpl(Closer closer, Utils utils, Injector injector, TypeLiteral<S> syncApi,
TypeLiteral<A> asyncApi, @Provider URI endpoint, @Provider String provider, @Identity String identity,
@ApiVersion String apiVersion) {
this.utils = utils;
this.asyncApi = injector.getInstance(Key.get(asyncApi));
this.syncApi = injector.getInstance(Key.get(syncApi));
@ -168,7 +168,7 @@ public class RestContextImpl<S, A> implements RestContext<S, A> {
@Override
public String toString() {
return "RestContextImpl [provider=" + provider + ", endpoint=" + endpoint + ", apiVersion="
+ apiVersion + ", identity=" + identity + "]";
return "RestContextImpl [provider=" + provider + ", endpoint=" + endpoint + ", apiVersion=" + apiVersion
+ ", identity=" + identity + "]";
}
}

View File

@ -18,11 +18,13 @@
*/
package org.jclouds.util;
import static com.google.common.base.Predicates.equalTo;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.jclouds.http.HttpUtils.changeSchemeHostAndPortTo;
import static org.jclouds.http.HttpUtils.parseQueryToMap;
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
import static org.testng.Assert.assertEquals;
import java.net.URI;
@ -35,6 +37,8 @@ import javax.ws.rs.core.UriBuilder;
import org.jboss.resteasy.specimpl.UriBuilderImpl;
import org.jclouds.PerformanceTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.HttpUtils;
import org.testng.annotations.Test;
@ -67,8 +71,8 @@ public class HttpUtilsTest extends PerformanceTest {
expects.put("Value", "dGVzdA==");
expects.put("InstanceId", "1");
assertEquals(
expects,
parseQueryToMap("Version=2010-06-15&Action=ModifyInstanceAttribute&Attribute=userData&Value=dGVzdA%3D%3D&InstanceId=1"));
expects,
parseQueryToMap("Version=2010-06-15&Action=ModifyInstanceAttribute&Attribute=userData&Value=dGVzdA%3D%3D&InstanceId=1"));
}
@Test
@ -77,24 +81,21 @@ public class HttpUtilsTest extends PerformanceTest {
assert parsedMap.keySet().size() == 1 : "Expected 1 key, found: " + parsedMap.keySet().size();
assert parsedMap.keySet().contains("v") : "Expected v to be a part of the keys";
String valueForV = Iterables.getOnlyElement(parsedMap.get("v"));
assert valueForV.equals("1.3") : "Expected the value for 'v' to be '1.3', found: "
+ valueForV;
assert valueForV.equals("1.3") : "Expected the value for 'v' to be '1.3', found: " + valueForV;
}
@Test
public void testParseQueryToMapMultiParam() {
Multimap<String, String> parsedMap = parseQueryToMap("v=1.3&sig=123");
assert parsedMap.keySet().size() == 2 : "Expected 2 keys, found: "
+ parsedMap.keySet().size();
assert parsedMap.keySet().size() == 2 : "Expected 2 keys, found: " + parsedMap.keySet().size();
assert parsedMap.keySet().contains("v") : "Expected v to be a part of the keys";
assert parsedMap.keySet().contains("sig") : "Expected sig to be a part of the keys";
String valueForV = Iterables.getOnlyElement(parsedMap.get("v"));
assert valueForV.equals("1.3") : "Expected the value for 'v' to be '1.3', found: "
+ valueForV;
assert valueForV.equals("1.3") : "Expected the value for 'v' to be '1.3', found: " + valueForV;
String valueForSig = Iterables.getOnlyElement(parsedMap.get("sig"));
assert valueForSig.equals("123") : "Expected the value for 'v' to be '123', found: "
+ valueForSig;
assert valueForSig.equals("123") : "Expected the value for 'v' to be '123', found: " + valueForSig;
}
@Test
public void testChangeSchemeHostAndPortTo() {
HttpRequest request = createMock(HttpRequest.class);
@ -114,28 +115,24 @@ public class HttpUtilsTest extends PerformanceTest {
public void testNoDoubleEncode() {
assertEquals(HttpUtils.urlEncode("/read-tests/%73%6f%6d%65%20%66%69%6c%65", '/'),
"/read-tests/%73%6f%6d%65%20%66%69%6c%65");
"/read-tests/%73%6f%6d%65%20%66%69%6c%65");
assertEquals(HttpUtils.urlEncode("/read-tests/ tep", '/'), "/read-tests/%20tep");
}
public void testIBM() {
URI ibm = HttpUtils
.createUri("https://www-180.ibm.com/cloud/enterprise/beta/ram/assetDetail/generalDetails.faces?guid={A31FF849-0E97-431A-0324-097385A46298}&v=1.2");
.createUri("https://www-180.ibm.com/cloud/enterprise/beta/ram/assetDetail/generalDetails.faces?guid={A31FF849-0E97-431A-0324-097385A46298}&v=1.2");
assertEquals(ibm.getQuery(), "guid={A31FF849-0E97-431A-0324-097385A46298}&v=1.2");
}
public void testAtmos() {
URI creds = HttpUtils
.createUri("compute://domain/user:Base64==@azureblob/container-hyphen/prefix");
assertEquals(creds, URI
.create("compute://domain%2Fuser:Base64%3D%3D@azureblob/container-hyphen/prefix"));
URI creds = HttpUtils.createUri("compute://domain/user:Base64==@azureblob/container-hyphen/prefix");
assertEquals(creds, URI.create("compute://domain%2Fuser:Base64%3D%3D@azureblob/container-hyphen/prefix"));
}
public void testAzure() {
URI creds = HttpUtils
.createUri("compute://identity:Base64==@azureblob/container-hyphen/prefix");
assertEquals(creds, URI
.create("compute://identity:Base64==@azureblob/container-hyphen/prefix"));
URI creds = HttpUtils.createUri("compute://identity:Base64==@azureblob/container-hyphen/prefix");
assertEquals(creds, URI.create("compute://identity:Base64==@azureblob/container-hyphen/prefix"));
}
public void testHosting() {
@ -181,13 +178,18 @@ public class HttpUtilsTest extends PerformanceTest {
}
public void testPercent() {
URI creds = HttpUtils
.createUri("https://jclouds.blob.core.windows.net/jclouds-getpath/write-tests/file1%.txt");
URI creds = HttpUtils.createUri("https://jclouds.blob.core.windows.net/jclouds-getpath/write-tests/file1%.txt");
assertEquals(
creds,
URI
.create("https://jclouds.blob.core.windows.net/jclouds-getpath/write-tests/file1%25.txt"));
assertEquals(creds, URI.create("https://jclouds.blob.core.windows.net/jclouds-getpath/write-tests/file1%25.txt"));
}
public void test404() {
Exception from = new HttpResponseException("message", null, new HttpResponse(404, "not found", null));
assertEquals(returnValueOnCodeOrNull(from, true, equalTo(404)), Boolean.TRUE);
}
public void testNullResponse() {
Exception from = new HttpResponseException("message", null, null);
assertEquals(returnValueOnCodeOrNull(from, true, equalTo(404)), null);
}
}

View File

@ -18,23 +18,20 @@
*/
package org.jclouds.rackspace.cloudfiles.functions;
import static com.google.common.base.Predicates.in;
import static com.google.common.collect.ImmutableSet.of;
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
import static org.jclouds.util.Utils.propagateOrNull;
import org.jclouds.http.HttpResponseException;
import javax.inject.Singleton;
import com.google.common.base.Function;
@Singleton
public class ReturnTrueOn404FalseOn409 implements Function<Exception, Boolean> {
public Boolean apply(Exception from) {
if (from instanceof HttpResponseException) {
HttpResponseException responseException = (HttpResponseException) from;
if (responseException.getResponse().getStatusCode() == 404) {
return true;
} else if (responseException.getResponse().getStatusCode() == 409) {
return false;
}
}
return Boolean.class.cast(propagateOrNull(from));
Boolean returnVal = returnValueOnCodeOrNull(from, true, in(of(404, 409)));
return returnVal != null ? returnVal : Boolean.class.cast(propagateOrNull(from));
}
}