mirror of https://github.com/apache/jclouds.git
Added annotation for throwing exception with Error object on 4xx status codes, and implemented in TaskClient
This commit is contained in:
parent
c771b2ac87
commit
412dd45ce1
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.vcloud.director.v1_5;
|
||||
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Error;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Task;
|
||||
|
||||
/**
|
||||
* @author grkvlt@apache.org
|
||||
*/
|
||||
public class VCloudDirectorException extends RuntimeException {
|
||||
|
||||
/** The serialVersionUID. */
|
||||
private static final long serialVersionUID = -3200853408568729058L;
|
||||
|
||||
private final Error error;
|
||||
|
||||
public VCloudDirectorException(Error error) {
|
||||
super("Error: " + error.getMessage());
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public VCloudDirectorException(Task task) {
|
||||
super("Task error: " + task.getError().getMessage());
|
||||
this.error = task.getError();
|
||||
}
|
||||
|
||||
public Error getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
}
|
|
@ -29,8 +29,12 @@ package org.jclouds.vcloud.director.v1_5;
|
|||
public interface VCloudDirectorMediaType {
|
||||
public final static String NS = "http://www.vmware.com/vcloud/v1.5";
|
||||
|
||||
public final static String ANY = "*/*";
|
||||
|
||||
public final static String SESSION_XML = "application/vnd.vmware.vcloud.session+xml";
|
||||
|
||||
public final static String ERROR_XML = "application/vnd.vmware.vcloud.error+xml";
|
||||
|
||||
public final static String ORGLIST_XML = "application/vnd.vmware.vcloud.orgList+xml";
|
||||
|
||||
public final static String METADATA_XML = "application/vnd.vmware.vcloud.metadata+xml";
|
||||
|
|
|
@ -30,10 +30,10 @@ import org.jclouds.rest.annotations.EndpointParam;
|
|||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.JAXBResponseParser;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Task;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.TasksList;
|
||||
import org.jclouds.vcloud.director.v1_5.filters.AddVCloudAuthorizationToRequest;
|
||||
import org.jclouds.vcloud.director.v1_5.functions.ThrowVCloudErrorOn4xxOrNull;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
|
@ -51,7 +51,7 @@ public interface TaskAsyncClient {
|
|||
@Path("/tasksList/{id}")
|
||||
@Consumes
|
||||
@JAXBResponseParser
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
@ExceptionParser(ThrowVCloudErrorOn4xxOrNull.class)
|
||||
ListenableFuture<TasksList> getTaskList(@PathParam("id") String orgId);
|
||||
|
||||
/**
|
||||
|
@ -60,7 +60,7 @@ public interface TaskAsyncClient {
|
|||
@GET
|
||||
@Consumes
|
||||
@JAXBResponseParser
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
@ExceptionParser(ThrowVCloudErrorOn4xxOrNull.class)
|
||||
ListenableFuture<Task> getTask(@EndpointParam URI taskHref);
|
||||
|
||||
/**
|
||||
|
@ -70,6 +70,6 @@ public interface TaskAsyncClient {
|
|||
@Path("/action/cancel")
|
||||
@Consumes
|
||||
@JAXBResponseParser
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
@ExceptionParser(ThrowVCloudErrorOn4xxOrNull.class)
|
||||
void cancelTask(@EndpointParam URI taskHref);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.vcloud.director.v1_5.functions;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.xml.bind.JAXB;
|
||||
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.io.InputSuppliers;
|
||||
import org.jclouds.vcloud.director.v1_5.VCloudDirectorException;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Error;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* @author grkvlt@apache.org
|
||||
*/
|
||||
@Singleton
|
||||
public class ThrowVCloudErrorOn4xxOrNull implements Function<Exception, Object> {
|
||||
@Inject
|
||||
private ThrowVCloudErrorOn4xxOrNull() { }
|
||||
|
||||
@Override
|
||||
public Object apply(Exception from) {
|
||||
Iterable<HttpResponseException> throwables = Iterables.filter(Throwables.getCausalChain(from), HttpResponseException.class);
|
||||
if (Iterables.size(throwables) == 1) {
|
||||
HttpResponseException exception = Iterables.getOnlyElement(throwables);
|
||||
if (exception.getResponse().getStatusCode() >= 400 && exception.getResponse().getStatusCode() < 500) {
|
||||
try {
|
||||
Error error = JAXB.unmarshal(InputSuppliers.of(exception.getContent()).getInput(), Error.class);
|
||||
throw new VCloudDirectorException(error);
|
||||
} catch (IOException e) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null; // TODO is this correct?
|
||||
}
|
||||
|
||||
}
|
|
@ -25,16 +25,16 @@ import java.net.URI;
|
|||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.vcloud.director.v1_5.VCloudDirectorClient;
|
||||
import org.jclouds.vcloud.director.v1_5.VCloudDirectorException;
|
||||
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Error;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Reference;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Task;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.TasksList;
|
||||
import org.jclouds.vcloud.director.v1_5.internal.BaseVCloudDirectorRestClientExpectTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* Test the {@link TaskClient} by observing its side effects.
|
||||
|
@ -48,7 +48,7 @@ public class TaskClientExpectTest extends BaseVCloudDirectorRestClientExpectTest
|
|||
public void testTaskListForValidOrg() {
|
||||
HttpRequest orgListRequest = HttpRequest.builder()
|
||||
.method("GET")
|
||||
.endpoint(URI.create("http://localhost/api/tasksList/6f312e42-cd2b-488d-a2bb-97519cd57ed0"))
|
||||
.endpoint(URI.create(endpoint + "/tasksList/6f312e42-cd2b-488d-a2bb-97519cd57ed0"))
|
||||
.headers(ImmutableMultimap.<String, String> builder()
|
||||
.put("Accept", "*/*")
|
||||
.put("x-vcloud-authorization", token)
|
||||
|
@ -57,14 +57,14 @@ public class TaskClientExpectTest extends BaseVCloudDirectorRestClientExpectTest
|
|||
|
||||
HttpResponse orgListResponse = HttpResponse.builder()
|
||||
.statusCode(200)
|
||||
.payload(payloadFromResourceWithContentType("/taskslist.xml", VCloudDirectorMediaType.TASKSLIST_XML + ";version=1.5"))
|
||||
.payload(payloadFromResourceWithContentType("/task/taskslist.xml", VCloudDirectorMediaType.TASKSLIST_XML + ";version=1.5"))
|
||||
.build();
|
||||
|
||||
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, orgListRequest, orgListResponse);
|
||||
|
||||
String orgId =Iterables.getLast(Splitter.on("/").split(URI.create("https://vcloudbeta.bluelock.com/api/org/6f312e42-cd2b-488d-a2bb-97519cd57ed0").getPath()));
|
||||
String orgId = getUuidFromReference.apply(Reference.builder().href(URI.create("https://vcloudbeta.bluelock.com/api/org/6f312e42-cd2b-488d-a2bb-97519cd57ed0")).build());
|
||||
|
||||
assertEquals(client.getTaskClient().getTaskList(orgId), TasksList.builder()
|
||||
TasksList expected = TasksList.builder()
|
||||
.name("Tasks Lists")
|
||||
.type("application/vnd.vmware.vcloud.tasksList+xml")
|
||||
.href(URI.create("https://vcloudbeta.bluelock.com/api/tasksList/6f312e42-cd2b-488d-a2bb-97519cd57ed0"))
|
||||
|
@ -117,7 +117,79 @@ public class TaskClientExpectTest extends BaseVCloudDirectorRestClientExpectTest
|
|||
.href(URI.create("https://vcloudbeta.bluelock.com/api/org/6f312e42-cd2b-488d-a2bb-97519cd57ed0"))
|
||||
.build())
|
||||
.build())
|
||||
.build()
|
||||
);
|
||||
.build();
|
||||
|
||||
assertEquals(client.getTaskClient().getTaskList(orgId), expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTaskListForInvalidOrgId() {
|
||||
HttpRequest orgListRequest = HttpRequest.builder()
|
||||
.method("GET")
|
||||
.endpoint(URI.create(endpoint + "/tasksList/NOTAUUID"))
|
||||
.headers(ImmutableMultimap.<String, String> builder()
|
||||
.put("Accept", "*/*")
|
||||
.put("x-vcloud-authorization", token)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
HttpResponse orgListResponse = HttpResponse.builder()
|
||||
.statusCode(400)
|
||||
.payload(payloadFromResourceWithContentType("/task/error400.xml", VCloudDirectorMediaType.ERROR_XML + ";version=1.5"))
|
||||
.build();
|
||||
|
||||
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, orgListRequest, orgListResponse);
|
||||
|
||||
String orgId = "NOTAUUID";
|
||||
|
||||
Error expected = Error.builder()
|
||||
.message("validation error on field 'id': String value has invalid format or length")
|
||||
.majorErrorCode(400)
|
||||
.minorErrorCode("BAD_REQUEST")
|
||||
.build();
|
||||
try {
|
||||
client.getTaskClient().getTaskList(orgId);
|
||||
fail("Should give HTTP 400 error");
|
||||
} catch (VCloudDirectorException vde) {
|
||||
assertEquals(vde.getError(), expected);
|
||||
} catch (Exception e) {
|
||||
fail("Should have thrown a VCloudDirectorException");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTaskListForNotFoundOrgId() {
|
||||
HttpRequest orgListRequest = HttpRequest.builder()
|
||||
.method("GET")
|
||||
.endpoint(URI.create(endpoint + "/tasksList/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"))
|
||||
.headers(ImmutableMultimap.<String, String> builder()
|
||||
.put("Accept", "*/*")
|
||||
.put("x-vcloud-authorization", token)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
HttpResponse orgListResponse = HttpResponse.builder()
|
||||
.statusCode(403)
|
||||
.payload(payloadFromResourceWithContentType("/task/error403.xml", VCloudDirectorMediaType.ERROR_XML + ";version=1.5"))
|
||||
.build();
|
||||
|
||||
VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, orgListRequest, orgListResponse);
|
||||
|
||||
String orgId = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
|
||||
|
||||
Error expected = Error.builder()
|
||||
.message("No access to entity \"com.vmware.vcloud.entity.org:aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\".")
|
||||
.majorErrorCode(403)
|
||||
.minorErrorCode("ACCESS_TO_RESOURCE_IS_FORBIDDEN")
|
||||
.build();
|
||||
|
||||
try {
|
||||
client.getTaskClient().getTaskList(orgId);
|
||||
fail("Should give HTTP 400 error");
|
||||
} catch (VCloudDirectorException vde) {
|
||||
assertEquals(vde.getError(), expected);
|
||||
} catch (Exception e) {
|
||||
fail("Should have thrown a VCloudDirectorException");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,13 @@ import org.jclouds.http.HttpResponse;
|
|||
import org.jclouds.rest.BaseRestClientExpectTest;
|
||||
import org.jclouds.vcloud.director.v1_5.VCloudDirectorClient;
|
||||
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.ReferenceType;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Guice;
|
||||
|
||||
/**
|
||||
|
@ -42,6 +46,7 @@ public class BaseVCloudDirectorRestClientExpectTest extends BaseRestClientExpect
|
|||
public static final String org = "JClouds";
|
||||
public static final String password = "password";
|
||||
public static final String token = "mIaR3/6Lna8DWImd7/JPR5rK8FcUHabt+G/UCJV5pJQ=";
|
||||
public static final String endpoint = "http://localhost/api";
|
||||
|
||||
protected DateService dateService;
|
||||
|
||||
|
@ -51,6 +56,14 @@ public class BaseVCloudDirectorRestClientExpectTest extends BaseRestClientExpect
|
|||
assert dateService != null;
|
||||
}
|
||||
|
||||
protected static final Function<ReferenceType<?>, String> getUuidFromReference = new Function<ReferenceType<?>, String>() {
|
||||
@Override
|
||||
public String apply(ReferenceType<?> input) {
|
||||
String uuid = Iterables.getLast(Splitter.on("/").split(input.getHref().getPath()));
|
||||
return uuid;
|
||||
}
|
||||
};
|
||||
|
||||
protected HttpRequest loginRequest = HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint(URI.create("http://localhost/api/sessions"))
|
||||
|
@ -75,17 +88,32 @@ public class BaseVCloudDirectorRestClientExpectTest extends BaseRestClientExpect
|
|||
credential = password;
|
||||
}
|
||||
|
||||
protected HttpRequest getStandardRequest(String method, String command) {
|
||||
return getStandardRequest(method, URI.create(endpoint + command));
|
||||
}
|
||||
|
||||
protected HttpRequest getStandardRequest(String method, URI uri) {
|
||||
return HttpRequest.builder().method(method).endpoint(uri).headers(
|
||||
ImmutableMultimap.<String, String> builder()
|
||||
.put("Accept", "*/*")
|
||||
.put("x-vcloud-authorization",token)
|
||||
.build()).build();
|
||||
return getStandardRequest(method, uri, VCloudDirectorMediaType.ANY);
|
||||
}
|
||||
|
||||
protected HttpRequest getStandardRequest(String method, URI uri, String mediaType) {
|
||||
return HttpRequest.builder()
|
||||
.method(method)
|
||||
.endpoint(uri)
|
||||
.headers(ImmutableMultimap.<String, String> builder()
|
||||
.put("Accept", mediaType)
|
||||
.put("x-vcloud-authorization", token)
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
protected HttpResponse getStandardPayloadResponse(String relativeFilePath, String mediaType) {
|
||||
return HttpResponse.builder().statusCode(200)
|
||||
.payload(payloadFromResourceWithContentType(relativeFilePath, mediaType+";version=1.5")).build();
|
||||
return getStandardPayloadResponse(200, relativeFilePath, mediaType);
|
||||
}
|
||||
|
||||
protected HttpResponse getStandardPayloadResponse(int statusCode, String relativeFilePath, String mediaType) {
|
||||
return HttpResponse.builder()
|
||||
.statusCode(statusCode)
|
||||
.payload(payloadFromResourceWithContentType(relativeFilePath, mediaType+";version=1.5")).build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Error xmlns="http://www.vmware.com/vcloud/v1.5" minorErrorCode="BAD_REQUEST" message="validation error on field 'id': String value has invalid format or length" majorErrorCode="400" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 http://vcloudbeta.bluelock.com/api/v1.5/schema/master.xsd"></Error>
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Error xmlns="http://www.vmware.com/vcloud/v1.5" minorErrorCode="ACCESS_TO_RESOURCE_IS_FORBIDDEN" message="No access to entity "com.vmware.vcloud.entity.org:aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"." majorErrorCode="403" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 http://vcloudbeta.bluelock.com/api/v1.5/schema/master.xsd"></Error>
|
Loading…
Reference in New Issue