Michael Pasternak has uploaded a new change for review. Change subject: restapi: SetupNetworks missing action link #806916 ......................................................................
restapi: SetupNetworks missing action link #806916 This patch adds generic support for actionin links generation under collection context https://bugzilla.redhat.com/show_bug.cgi?id=806916 Change-Id: Iea197cc0c6219061a3b83b5aa8fccbf18de29802 Signed-off-by: Michael Pasternak <[email protected]> --- M backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java M backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/model/ActionsBuilder.java A backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/ArrayUtils.java M backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd M backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendCollectionResource.java M backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostNicsResource.java M backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostNicsResourceTest.java 7 files changed, 129 insertions(+), 26 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/61/7461/1 diff --git a/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java b/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java index f0f32cb..7b45418 100644 --- a/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java +++ b/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java @@ -26,6 +26,7 @@ import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; +import org.ovirt.engine.api.model.ActionableResource; import org.ovirt.engine.api.model.ActionsBuilder; import org.ovirt.engine.api.model.BaseResource; import org.ovirt.engine.api.model.CdRom; @@ -591,6 +592,21 @@ } /** + * Adds the set of action links for an object + * + * @param uriInfo the URI info + * @param model the object to add actions to + * @param collection the object to get implemented methods from + * @return the object, including its set of action links + */ + public static <R extends ActionableResource> void addActions(UriInfo uriInfo, R model, Object collection) { + if (uriInfo != null) { + ActionsBuilder actionsBuilder = new ActionsBuilder(uriInfo, model.getClass(), collection.getClass()); + model.setActions(actionsBuilder.build()); + } + } + + /** * Set the href attribute on the object (and its inline objects) * and construct its set of action links * diff --git a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/model/ActionsBuilder.java b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/model/ActionsBuilder.java index 5fc16c0..8c15e18 100644 --- a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/model/ActionsBuilder.java +++ b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/model/ActionsBuilder.java @@ -21,31 +21,45 @@ import javax.ws.rs.Path; import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; + +import org.ovirt.engine.api.utils.ArrayUtils; + public class ActionsBuilder { private UriBuilder uriBuilder; private Class<?> service; + UriInfo uriInfo; + Class<?> collection; public ActionsBuilder(UriBuilder uriBuilder, Class<?> service) { this.uriBuilder = uriBuilder; this.service = service; } + public ActionsBuilder(UriInfo uriInfo, Class<?> service, Class<?> collection) { + this.uriInfo = uriInfo; + this.service = service; + this.collection = collection; + } + public Actions build() { Actions actions = null; - for (Method method : service.getMethods()) { + for (Method method : ArrayUtils.concat(service.getMethods(), getInterfaceSignatures(collection))) { Path path = method.getAnnotation(Path.class); Actionable actionable = method.getAnnotation(Actionable.class); if (actionable != null && path != null) { - URI uri = uriBuilder.clone().path(path.value()).build(); - Link link = new Link(); link.setRel(path.value()); - link.setHref(uri.toString()); - + if (uriBuilder != null) { + URI uri = uriBuilder.clone().path(path.value()).build(); + link.setHref(uri.toString()); + } else { + link.setHref(this.uriInfo.getPath()+'/'+link.getRel()); + } if (actions == null) { actions = new Actions(); } @@ -55,4 +69,14 @@ return actions; } + + private Method[] getInterfaceSignatures(Class<?> collection) { + Method[] methods = new Method[0]; + if (collection != null){ + for (Class<?> inter : collection.getInterfaces()){ + methods = ArrayUtils.concat(methods, inter.getMethods()); + } + } + return methods; + } } diff --git a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/ArrayUtils.java b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/ArrayUtils.java new file mode 100644 index 0000000..0354e53 --- /dev/null +++ b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/ArrayUtils.java @@ -0,0 +1,11 @@ +package org.ovirt.engine.api.utils; + +import java.util.Arrays; + +public class ArrayUtils { + public static <T> T[] concat(T[] first, T[] second) { + T[] result = Arrays.copyOf(first, first.length + second.length); + System.arraycopy(second, 0, result, first.length, second.length); + return result; + } +} diff --git a/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd b/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd index 96f32ba..5dfd307 100644 --- a/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd +++ b/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd @@ -810,33 +810,46 @@ <!-- Common to all resources --> - <xs:complexType name="BaseResource"> + <xs:complexType name="ActionableResource"> <xs:sequence> - <xs:element name="name" type="xs:string" minOccurs="0"/> - <xs:element name="description" type="xs:string" minOccurs="0"/> <xs:element name="actions" type="Actions" minOccurs="0"/> - <xs:element name="creation_status" type="Status" minOccurs="0"/> - <!-- also rel="creation_status" link for monitoring async creation --> - <!-- further link relation types may be defined by specific resources --> - <xs:element ref="link" minOccurs="0" maxOccurs="unbounded"> - <xs:annotation> - <xs:appinfo> - <jaxb:property name="Links"/> - </xs:appinfo> - </xs:annotation> - </xs:element> </xs:sequence> - <xs:attribute name="href" type="xs:string"/> - <xs:attribute name="id" type="xs:string"/> + </xs:complexType> + + <xs:complexType name="BaseResource"> + <xs:complexContent> + <xs:extension base="ActionableResource"> + <xs:sequence> + <xs:element name="name" type="xs:string" minOccurs="0"/> + <xs:element name="description" type="xs:string" minOccurs="0"/> + <xs:element name="creation_status" type="Status" minOccurs="0"/> + <!-- also rel="creation_status" link for monitoring async creation --> + <!-- further link relation types may be defined by specific resources --> + <xs:element ref="link" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:appinfo> + <jaxb:property name="Links"/> + </xs:appinfo> + </xs:annotation> + </xs:element> + </xs:sequence> + <xs:attribute name="href" type="xs:string"/> + <xs:attribute name="id" type="xs:string"/> + </xs:extension> + </xs:complexContent> </xs:complexType> <xs:complexType name="BaseResources"> - <xs:sequence> - <xs:element name="total" type="xs:unsignedInt" minOccurs="0"/> - <xs:element name="active" type="xs:unsignedInt" minOccurs="0"/> - </xs:sequence> + <xs:complexContent> + <xs:extension base="ActionableResource"> + <xs:sequence> + <xs:element name="total" type="xs:unsignedInt" minOccurs="0"/> + <xs:element name="active" type="xs:unsignedInt" minOccurs="0"/> + </xs:sequence> + </xs:extension> + </xs:complexContent> </xs:complexType> - + <xs:complexType name="Option"> <xs:attribute name="name" type="xs:string"/> <xs:attribute name="value" type="xs:string"/> diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendCollectionResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendCollectionResource.java index 0fe8b39..ab5566e 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendCollectionResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendCollectionResource.java @@ -9,8 +9,10 @@ import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; +import org.ovirt.engine.api.common.util.LinkHelper; import org.ovirt.engine.api.common.util.QueryHelper; import org.ovirt.engine.api.common.util.StatusUtils; +import org.ovirt.engine.api.model.ActionableResource; import org.ovirt.engine.api.model.BaseResource; import org.ovirt.engine.core.common.action.VdcActionParametersBase; import org.ovirt.engine.core.common.action.VdcActionType; @@ -224,4 +226,14 @@ } return null; } + + /** + * + * @param model the resource to add actions to + * @return collection with action links + */ + protected <C extends ActionableResource> C addActions(C model) { + LinkHelper.addActions(getUriInfo(), model, this); + return model; + } } diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostNicsResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostNicsResource.java index faed271..023c543 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostNicsResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostNicsResource.java @@ -72,7 +72,7 @@ } ret.getHostNics().add(addLinks(hostNic)); } - return ret; + return addActions(ret); } @SuppressWarnings("serial") diff --git a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostNicsResourceTest.java b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostNicsResourceTest.java index e19be91..c163123 100644 --- a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostNicsResourceTest.java +++ b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendHostNicsResourceTest.java @@ -3,6 +3,7 @@ import static org.easymock.EasyMock.expect; import static org.junit.Assert.*; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; @@ -52,6 +53,8 @@ private static final Integer NIC_SPEED = 100; private static final InterfaceStatus NIC_STATUS = InterfaceStatus.Up; private static final NetworkBootProtocol BOOT_PROTOCOL = NetworkBootProtocol.StaticIp; + private static final String SETUPNETWORKS_ACTION_BASE_URL = "/hosts/00000000-0000-0000-0000-000000000000/nics"; + private static final String SETUPNETWORKS_ACTION_URL = "/hosts/00000000-0000-0000-0000-000000000000/nics/setupnetworks@SLTests"; public BackendHostNicsResourceTest() { super(new BackendHostNicsResource(PARENT_GUID.toString()), null, null); @@ -274,6 +277,30 @@ verifyCollection(getCollection()); } + @Test + public void testActionsInList() throws Exception { + UriInfo uriInfo = setUpActionsUriExpectations(); + setGetVdsQueryExpectations(1); + setGetNetworksQueryExpectations(1); + setUpQueryExpectations(""); + collection.setUriInfo(uriInfo); + verifyActions(collection.list()); + } + + private UriInfo setUpActionsUriExpectations() { + UriInfo uriInfo = control.createMock(UriInfo.class); + expect(uriInfo.getBaseUri()).andReturn(URI.create(BASE_PATH)).anyTimes(); + expect(uriInfo.getPath()).andReturn(SETUPNETWORKS_ACTION_BASE_URL).anyTimes(); + return uriInfo; + } + + private void verifyActions(HostNics list) { + assertNotNull(list.getActions()); + assertNotNull(list.getActions().getLinks()); + assertNotNull(list.getActions().getLinks().get(0)); + assertEquals(list.getActions().getLinks().get(0).getHref(), SETUPNETWORKS_ACTION_URL); + } + protected void doTestBadRemove(boolean canDo, boolean success, String detail) throws Exception { setGetVdsQueryExpectations(1); setGetNetworksQueryExpectations(1); -- To view, visit http://gerrit.ovirt.org/7461 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Iea197cc0c6219061a3b83b5aa8fccbf18de29802 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Michael Pasternak <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
