mirror of https://github.com/apache/jclouds.git
nicer NPE when null args are specified to ReST methods
This commit is contained in:
parent
085bc43d48
commit
85b5006084
|
@ -140,6 +140,7 @@ import com.google.common.annotations.VisibleForTesting;
|
|||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Functions;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
|
@ -1014,7 +1015,7 @@ public class RestAnnotationProcessor<T> {
|
|||
|
||||
Annotation[] annotations = request.getJavaMethod().getParameterAnnotations()[entry.getKey()];
|
||||
for (Annotation a : annotations) {
|
||||
if (Nullable.class.isAssignableFrom(a.annotationType()))
|
||||
if (NULLABLE.apply(a))
|
||||
continue OUTER;
|
||||
}
|
||||
Preconditions.checkNotNull(null, request.getJavaMethod().getName() + " parameter " + (entry.getKey() + 1));
|
||||
|
@ -1188,17 +1189,11 @@ public class RestAnnotationProcessor<T> {
|
|||
for (Annotation key : entry.getValue()) {
|
||||
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
||||
String paramKey = ((PathParam) key).value();
|
||||
String paramValue;
|
||||
if (extractors != null && extractors.size() > 0) {
|
||||
ParamParser extractor = (ParamParser) extractors.iterator().next();
|
||||
paramValue = injector.getInstance(extractor.value()).apply(args[entry.getKey()]);
|
||||
} else {
|
||||
paramValue = args[entry.getKey()].toString();
|
||||
}
|
||||
pathParamValues.put(paramKey, paramValue);
|
||||
Optional<?> paramValue = getParamValue(method, args, extractors, entry, paramKey);
|
||||
if (paramValue.isPresent())
|
||||
pathParamValues.put(paramKey, paramValue.get().toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (method.isAnnotationPresent(PathParam.class) && method.isAnnotationPresent(ParamParser.class)) {
|
||||
String paramKey = method.getAnnotation(PathParam.class).value();
|
||||
String paramValue = injector.getInstance(method.getAnnotation(ParamParser.class).value()).apply(args);
|
||||
|
@ -1208,6 +1203,33 @@ public class RestAnnotationProcessor<T> {
|
|||
return pathParamValues;
|
||||
}
|
||||
|
||||
protected Optional<?> getParamValue(Method method, Object[] args, Set<Annotation> extractors,
|
||||
Entry<Integer, Set<Annotation>> entry, String paramKey) {
|
||||
Object arg = args[entry.getKey()];
|
||||
if (arg == null && containsNullable(method.getParameterAnnotations()[entry.getKey()]))
|
||||
return Optional.absent();
|
||||
|
||||
checkNotNull(arg, "param{%s} for method %s.%s", paramKey, method.getDeclaringClass().getSimpleName(),
|
||||
method.getName());
|
||||
if (extractors != null && extractors.size() > 0) {
|
||||
ParamParser extractor = (ParamParser) extractors.iterator().next();
|
||||
return Optional.of(injector.getInstance(extractor.value()).apply(arg));
|
||||
}
|
||||
return Optional.of(arg);
|
||||
}
|
||||
|
||||
private static final Predicate<Annotation> NULLABLE = new Predicate<Annotation>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(Annotation in) {
|
||||
return Nullable.class.isAssignableFrom(in.annotationType());
|
||||
}
|
||||
};
|
||||
|
||||
private static boolean containsNullable(Annotation[] annotations) {
|
||||
return Iterables.any(ImmutableSet.copyOf(annotations), NULLABLE);
|
||||
}
|
||||
|
||||
private Multimap<String, String> encodeValues(Multimap<String, String> unencoded, char... skips) {
|
||||
Multimap<String, String> encoded = LinkedHashMultimap.create();
|
||||
for (Entry<String, String> entry : unencoded.entries()) {
|
||||
|
@ -1226,14 +1248,9 @@ public class RestAnnotationProcessor<T> {
|
|||
for (Annotation key : entry.getValue()) {
|
||||
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
||||
String paramKey = ((MatrixParam) key).value();
|
||||
String paramValue;
|
||||
if (extractors != null && extractors.size() > 0) {
|
||||
ParamParser extractor = (ParamParser) extractors.iterator().next();
|
||||
paramValue = injector.getInstance(extractor.value()).apply(args[entry.getKey()]);
|
||||
} else {
|
||||
paramValue = args[entry.getKey()].toString();
|
||||
}
|
||||
matrixParamValues.put(paramKey, paramValue);
|
||||
Optional<?> paramValue = getParamValue(method, args, extractors, entry, paramKey);
|
||||
if (paramValue.isPresent())
|
||||
matrixParamValues.put(paramKey, paramValue.get().toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1257,16 +1274,9 @@ public class RestAnnotationProcessor<T> {
|
|||
for (Annotation key : entry.getValue()) {
|
||||
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
||||
String paramKey = ((FormParam) key).value();
|
||||
String paramValue;
|
||||
if (extractors != null && extractors.size() > 0) {
|
||||
ParamParser extractor = (ParamParser) extractors.iterator().next();
|
||||
paramValue = injector.getInstance(extractor.value()).apply(args[entry.getKey()]);
|
||||
} else {
|
||||
Object pvo = args[entry.getKey()];
|
||||
Preconditions.checkNotNull(pvo, paramKey);
|
||||
paramValue = pvo.toString();
|
||||
}
|
||||
formParamValues.put(paramKey, paramValue);
|
||||
Optional<?> paramValue = getParamValue(method, args, extractors, entry, paramKey);
|
||||
if (paramValue.isPresent())
|
||||
formParamValues.put(paramKey, paramValue.get().toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1289,16 +1299,9 @@ public class RestAnnotationProcessor<T> {
|
|||
for (Annotation key : entry.getValue()) {
|
||||
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
||||
String paramKey = ((QueryParam) key).value();
|
||||
Object paramValue;
|
||||
if (extractors != null && extractors.size() > 0) {
|
||||
ParamParser extractor = (ParamParser) extractors.iterator().next();
|
||||
paramValue = injector.getInstance(extractor.value()).apply(args[entry.getKey()]);
|
||||
} else {
|
||||
paramValue = args[entry.getKey()];
|
||||
}
|
||||
if (paramValue != null) {
|
||||
queryParamValues.put(paramKey, paramValue.toString());
|
||||
}
|
||||
Optional<?> paramValue = getParamValue(method, args, extractors, entry, paramKey);
|
||||
if (paramValue.isPresent())
|
||||
queryParamValues.put(paramKey, paramValue.get().toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1321,15 +1324,9 @@ public class RestAnnotationProcessor<T> {
|
|||
for (Annotation key : entry.getValue()) {
|
||||
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
||||
String paramKey = ((PayloadParam) key).value();
|
||||
Object paramValue;
|
||||
if (extractors != null && extractors.size() > 0) {
|
||||
ParamParser extractor = (ParamParser) extractors.iterator().next();
|
||||
paramValue = injector.getInstance(extractor.value()).apply(args[entry.getKey()]);
|
||||
} else {
|
||||
paramValue = args[entry.getKey()] != null ? args[entry.getKey()] : null;
|
||||
}
|
||||
postParams.put(paramKey, paramValue);
|
||||
|
||||
Optional<?> paramValue = getParamValue(method, args, extractors, entry, paramKey);
|
||||
if (paramValue.isPresent())
|
||||
postParams.put(paramKey, paramValue.get());
|
||||
}
|
||||
}
|
||||
return postParams;
|
||||
|
|
|
@ -499,6 +499,12 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
|||
@QueryParams(keys = { "foo", "fooble" }, values = { "bar", "baz" })
|
||||
public void foo3(@QueryParam("robbie") String robbie) {
|
||||
}
|
||||
|
||||
@FOO
|
||||
@Path("/")
|
||||
@QueryParams(keys = { "foo", "fooble" }, values = { "bar", "baz" })
|
||||
public void foo3Nullable(@Nullable @QueryParam("robbie") String robbie) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnEncodeQuery() {
|
||||
|
@ -537,6 +543,25 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
|||
assertEquals(request.getEndpoint().getQuery(), "x-ms-version=2009-07-17&foo=bar&fooble=baz&robbie=wonder");
|
||||
assertEquals(request.getMethod(), "FOO");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNiceNPEQueryParam() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = TestQuery.class.getMethod("foo3", String.class);
|
||||
try {
|
||||
factory(TestPath.class).createRequest(method, (String) null);
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals(e.getMessage(), "param{robbie} for method TestQuery.foo3");
|
||||
}
|
||||
}
|
||||
|
||||
public void testNoNPEOnQueryParamWithNullable() throws SecurityException, NoSuchMethodException {
|
||||
Method method = TestQuery.class.getMethod("foo3Nullable", String.class);
|
||||
HttpRequest request = factory(TestPath.class).createRequest(method, (String) null);
|
||||
assertEquals(request.getEndpoint().getHost(), "localhost");
|
||||
assertEquals(request.getEndpoint().getPath(), "/");
|
||||
assertEquals(request.getEndpoint().getQuery(), "foo=bar&fooble=baz");
|
||||
assertEquals(request.getMethod(), "FOO");
|
||||
}
|
||||
|
||||
public interface TestPayloadParamVarargs {
|
||||
@POST
|
||||
|
@ -578,7 +603,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
|||
assertNonPayloadHeadersEqual(request, "");
|
||||
assertPayloadEquals(request, "foo", "application/octet-stream", false);
|
||||
}
|
||||
|
||||
|
||||
public void testHttpRequestWithOnlyContentType() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = TestPayloadParamVarargs.class.getMethod("post", HttpRequestOptions.class);
|
||||
HttpRequest request = factory(TestPayloadParamVarargs.class).createRequest(method, new TestHttpRequestOptions().payload("fooya"));
|
||||
|
@ -1397,6 +1422,11 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
|||
@Path("/{path}")
|
||||
public void onePath(@PathParam("path") String path) {
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{path}")
|
||||
public void onePathNullable(@Nullable @PathParam("path") String path) {
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{path1}/{path2}")
|
||||
|
@ -1435,7 +1465,17 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
|||
public void onePathParamExtractorMethod(String path) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNiceNPEPathParam() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = TestPath.class.getMethod("onePath", String.class);
|
||||
try {
|
||||
factory(TestPath.class).createRequest(method, (String) null);
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals(e.getMessage(), "param{path} for method TestPath.onePath");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathParamExtractor() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = TestPath.class.getMethod("onePathParamExtractor", String.class);
|
||||
|
@ -1462,7 +1502,17 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
|||
assertNonPayloadHeadersEqual(request, "");
|
||||
assertPayloadEquals(request, null, null, false);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNiceNPEMatrixParam() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = TestPath.class.getMethod("oneMatrixParamExtractor", String.class);
|
||||
try {
|
||||
factory(TestPath.class).createRequest(method, (String) null);
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals(e.getMessage(), "param{one} for method TestPath.oneMatrixParamExtractor");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormParamExtractor() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = TestPath.class.getMethod("oneFormParamExtractor", String.class);
|
||||
|
@ -1471,7 +1521,17 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
|||
assertNonPayloadHeadersEqual(request, "");
|
||||
assertPayloadEquals(request, "one=l", "application/x-www-form-urlencoded", false);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNiceNPEFormParam() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = TestPath.class.getMethod("oneFormParamExtractor", String.class);
|
||||
try {
|
||||
factory(TestPath.class).createRequest(method, (String) null);
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals(e.getMessage(), "param{one} for method TestPath.oneFormParamExtractor");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParamExtractorMethod() throws SecurityException, NoSuchMethodException {
|
||||
Method method = TestPath.class.getMethod("onePathParamExtractorMethod", String.class);
|
||||
|
|
Loading…
Reference in New Issue