Bug #65 - Fix inconsistencies in the NB REST APIs
[controller.git] / opendaylight / northbound / topology / src / main / java / org / opendaylight / controller / topology / northbound / TopologyNorthboundJAXRS.java
index 3ba1eb18435612565e8c6f68c125d75bb951420c..ff26bfd21f30a6b67f683607924b366ef32a1011 100644 (file)
@@ -17,7 +17,7 @@ import java.util.concurrent.ConcurrentMap;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
-import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
@@ -52,11 +52,7 @@ import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig;
  * Authentication realm : <b>opendaylight</b><br>
  * Transport : <b>HTTP and HTTPS</b><br>
  * <br>
- * HTTPS Authentication is disabled by default. Administrator can enable it in
- * tomcat-server.xml after adding a proper keystore / SSL certificate from a
- * trusted authority.<br>
- * More info :
- * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ * HTTPS Authentication is disabled by default.
  */
 
 @Path("/")
@@ -66,7 +62,7 @@ public class TopologyNorthboundJAXRS {
 
     @Context
     public void setSecurityContext(SecurityContext context) {
-        username = context.getUserPrincipal().getName();
+        if (context != null && context.getUserPrincipal() != null) username = context.getUserPrincipal().getName();
     }
 
     protected String getUserName() {
@@ -78,12 +74,13 @@ public class TopologyNorthboundJAXRS {
      * Retrieve the Topology
      *
      * @param containerName
-     *            The container for which we want to retrieve the topology (Eg. 'default')
+     *            The container for which we want to retrieve the topology (Eg.
+     *            'default')
      *
-     * @return A List of EdgeProps each EdgeProp represent an Edge of the grap
+     * @return A List of EdgeProps each EdgeProp represent an Edge of the graph
      *         with the corresponding properties attached to it.
      *
-     * <pre>
+     *         <pre>
      *
      * Example:
      *
@@ -91,10 +88,87 @@ public class TopologyNorthboundJAXRS {
      * http://localhost:8080/controller/nb/v2/topology/default
      *
      * Response in XML:
-     * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;&lt;topology&gt;&lt;edgeProperties&gt;&lt;edge&gt;&lt;tailNodeConnector id="2" type="OF"&gt;&lt;node id="00:00:00:00:00:00:00:02" type="OF"/&gt;&lt;/tailNodeConnector&gt;&lt;headNodeConnector id="2" type="OF"&gt;&lt;node id="00:00:00:00:00:00:00:51" type="OF"/&gt;&lt;/headNodeConnector&gt;&lt;/edge&gt;&lt;properties&gt;&lt;state&gt;&lt;value&gt;1&lt;/value&gt;&lt;/state&gt;&lt;config&gt;&lt;value&gt;1&lt;/value&gt;&lt;/config&gt;&lt;name&gt;&lt;value&gt;C1_2-L2_2&lt;/value&gt;&lt;/name&gt;&lt;timeStamp&gt;&lt;value&gt;1377279422032&lt;/value&gt;&lt;name&gt;creation&lt;/name&gt;&lt;/timeStamp&gt;&lt;/properties&gt;&lt;/edgeProperties&gt;&lt;edgeProperties&gt;&lt;edge&gt;&lt;tailNodeConnector id="2" type="OF"&gt;&lt;node id="00:00:00:00:00:00:00:51" type="OF"/&gt;&lt;/tailNodeConnector&gt;&lt;headNodeConnector id="2" type="OF"&gt;&lt;node id="00:00:00:00:00:00:00:02" type="OF"/&gt;&lt;/headNodeConnector&gt;&lt;/edge&gt;&lt;properties&gt;&lt;state&gt;&lt;value&gt;1&lt;/value&gt;&lt;/state&gt;&lt;name&gt;&lt;value&gt;L2_2-C1_2&lt;/value&gt;&lt;/name&gt;&lt;config&gt;&lt;value&gt;1&lt;/value&gt;&lt;/config&gt;&lt;timeStamp&gt;&lt;value&gt;1377279423564&lt;/value&gt;&lt;name&gt;creation&lt;/name&gt;&lt;/timeStamp&gt;&lt;/properties&gt;&lt;/edgeProperties&gt;&lt;/topology&gt;
+     * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
+     * &lt;topology&gt;
+     *     &lt;edgeProperties&gt;
+     *         &lt;edge&gt;
+     *             &lt;tailNodeConnector&gt;
+     *                 &lt;node&gt;
+     *                     &lt;id&gt;00:00:00:00:00:00:00:02&lt;/id&gt;
+     *                     &lt;type&gt;OF&lt;/type&gt;
+     *                 &lt;/node&gt;
+     *                 &lt;id&gt;2&lt;/id&gt;
+     *                 &lt;type&gt;OF&lt;/type&gt;
+     *             &lt;/tailNodeConnector&gt;
+     *             &lt;headNodeConnector&gt;
+     *                 &lt;node&gt;
+     *                     &lt;id&gt;00:00:00:00:00:00:00:51&lt;/id&gt;
+     *                     &lt;type&gt;OF&lt;/type&gt;
+     *                 &lt;/node&gt;
+     *                 &lt;id&gt;2&lt;/id&gt;
+     *                 &lt;type&gt;OF&lt;/type&gt;
+     *             &lt;/headNodeConnector&gt;
+     *         &lt;/edge&gt;
+     *         &lt;properties&gt;
+     *             &lt;state&gt;
+     *                 &lt;value&gt;1&lt;/value&gt;
+     *             &lt;/state&gt;
+     *             &lt;config&gt;
+     *                 &lt;value&gt;1&lt;/value&gt;
+     *             &lt;/config&gt;
+     *             &lt;name&gt;
+     *                 &lt;value&gt;C1_2-L2_2&lt;/value&gt;
+     *             &lt;/name&gt;
+     *             &lt;timeStamp&gt;
+     *                 &lt;value&gt;1377279422032&lt;/value&gt;
+     *                 &lt;name&gt;creation&lt;/name&gt;
+     *             &lt;/timeStamp&gt;
+     *         &lt;/properties&gt;
+     *     &lt;/edgeProperties&gt;
+     *     &lt;edgeProperties&gt;
+     *         &lt;edge&gt;
+     *             &lt;tailNodeConnector&gt;
+     *                 &lt;node&gt;
+     *                     &lt;id&gt;00:00:00:00:00:00:00:51&lt;/id&gt;
+     *                     &lt;type&gt;OF&lt;/type&gt;
+     *                 &lt;/node&gt;
+     *                 &lt;id&gt;2&lt;/id&gt;
+     *                 &lt;type&gt;OF&lt;/type&gt;
+     *             &lt;/tailNodeConnector&gt;
+     *             &lt;headNodeConnector&gt;
+     *                 &lt;node&gt;
+     *                     &lt;id&gt;00:00:00:00:00:00:00:02&lt;/id&gt;
+     *                     &lt;type&gt;OF&lt;/type&gt;
+     *                 &lt;/node&gt;
+     *                 &lt;id&gt;2&lt;/id&gt;
+     *                 &lt;type&gt;OF&lt;/type&gt;
+     *             &lt;/headNodeConnector&gt;
+     *         &lt;/edge&gt;
+     *         &lt;properties&gt;
+     *             &lt;state&gt;
+     *                 &lt;value&gt;1&lt;/value&gt;
+     *             &lt;/state&gt;
+     *             &lt;name&gt;
+     *                 &lt;value&gt;L2_2-C1_2&lt;/value&gt;
+     *             &lt;/name&gt;
+     *             &lt;config&gt;
+     *                 &lt;value&gt;1&lt;/value&gt;
+     *             &lt;/config&gt;
+     *             &lt;timeStamp&gt;
+     *                 &lt;value&gt;1377279423564&lt;/value&gt;
+     *                 &lt;name&gt;creation&lt;/name&gt;
+     *             &lt;/timeStamp&gt;
+     *         &lt;/properties&gt;
+     *     &lt;/edgeProperties&gt;
+     * &lt;/topology&gt;
      *
      * Response in JSON:
-     * {"edgeProperties":[{"edge":{"tailNodeConnector":{"@id":"2","@type":"OF","node":{"@id":"00:00:00:00:00:00:00:02","@type":"OF"}},"headNodeConnector":{"@id":"2","@type":"OF","node":{"@id":"00:00:00:00:00:00:00:51","@type":"OF"}}},"properties":{"timeStamp":{"value":"1377278961017","name":"creation"}}},{"edge":{"tailNodeConnector":{"@id":"2","@type":"OF","node":{"@id":"00:00:00:00:00:00:00:51","@type":"OF"}},"headNodeConnector":{"@id":"2","@type":"OF","node":{"@id":"00:00:00:00:00:00:00:02","@type":"OF"}}},"properties":{"timeStamp":{"value":"1377278961018","name":"creation"}}}]}
+     * {"edgeProperties":[{"edge":{"tailNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:02","type":"OF"},
+     * "id":"2","type":"OF"},"headNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:51","type":"OF"},"id":
+     * "2","type":"OF"}},"properties":{"timeStamp":{"value":"1377278961017","name":"creation"}}},
+     * {"edge":{"tailNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:51","type":"OF"},"id":
+     * "2","type":"OF"}},"headNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:02","type":"OF"},
+     * "id":"2","type":"OF"}},"properties":{"timeStamp":{"value":"1377278961018","name":"creation"}}}]}
      *
      * </pre>
      */
@@ -122,8 +196,7 @@ public class TopologyNorthboundJAXRS {
         if (topo != null) {
             List<EdgeProperties> res = new ArrayList<EdgeProperties>();
             for (Map.Entry<Edge, Set<Property>> entry : topo.entrySet()) {
-                EdgeProperties el = new EdgeProperties(entry.getKey(),
-                        entry.getValue());
+                EdgeProperties el = new EdgeProperties(entry.getKey(), entry.getValue());
                 res.add(el);
             }
             return new Topology(res);
@@ -145,17 +218,26 @@ public class TopologyNorthboundJAXRS {
      * Example:
      *
      * RequestURL:
-     * http://localhost:8080/controller/nb/v2/topology/default/user-link
+     * http://localhost:8080/controller/nb/v2/topology/default/userLinks
      *
      * Response in XML:
-     * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;&lt;topologyUserLinks&gt;&lt;userLinks&gt;&lt;status&gt;Success&lt;/status&gt;&lt;name&gt;link1&lt;/name&gt;&lt;srcNodeConnector&gt;OF|2@OF|00:00:00:00:00:00:00:02&lt;/srcNodeConnector&gt;&lt;dstNodeConnector&gt;OF|2@OF|00:00:00:00:00:00:00:51&lt;/dstNodeConnector&gt;&lt;/userLinks&gt;&lt;/topologyUserLinks&gt;
+     * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
+     * &lt;topologyUserLinks&gt;
+     * &lt;userLinks&gt;
+     * &lt;status&gt;Success&lt;/status&gt;
+     * &lt;name&gt;link1&lt;/name&gt;
+     * &lt;srcNodeConnector&gt;OF|2@OF|00:00:00:00:00:00:00:02&lt;/srcNodeConnector&gt;
+     * &lt;dstNodeConnector&gt;OF|2@OF|00:00:00:00:00:00:00:51&lt;/dstNodeConnector&gt;
+     * &lt;/userLinks&gt;
+     * &lt;/topologyUserLinks&gt;
      *
      * Response in JSON:
-     * {"userLinks":{"status":"Success","name":"link1","srcNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:02","dstNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:51"}}
+     * {"userLinks":{"status":"Success","name":"link1","srcNodeConnector":
+     * "OF|2@OF|00:00:00:00:00:00:00:02","dstNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:51"}}
      *
      * </pre>
      */
-    @Path("/{containerName}/user-link")
+    @Path("/{containerName}/userLinks")
     @GET
     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
     @TypeHint(TopologyUserLinks.class)
@@ -192,6 +274,8 @@ public class TopologyNorthboundJAXRS {
      *
      * @param containerName
      *            Name of the Container (Eg. 'default')
+     * @param name
+     *            Name of the user link
      * @param TopologyUserLinkConfig
      *            in JSON or XML format
      * @return Response as dictated by the HTTP Response Status code
@@ -201,18 +285,24 @@ public class TopologyNorthboundJAXRS {
      * Example:
      *
      * RequestURL:
-     * http://localhost:8080/controller/nb/v2/topology/default/user-link/config1-content
+     * http://localhost:8080/controller/nb/v2/topology/default/userLink/link1
      *
      * Request in XML:
-     * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;&lt;topologyUserLinks&gt;&lt;status&gt;Success&lt;/status&gt;&lt;name&gt;link1&lt;/name&gt;&lt;srcNodeConnector&gt;OF|2@OF|00:00:00:00:00:00:00:02&lt;/srcNodeConnector&gt;&lt;dstNodeConnector&gt;OF|2@OF|00:00:00:00:00:00:00:51&lt;/dstNodeConnector&gt;&lt;/topologyUserLinks&gt;
+     * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
+     * &lt;topologyUserLinks&gt;
+     * &lt;status&gt;Success&lt;/status&gt;
+     * &lt;name&gt;link1&lt;/name&gt;
+     * &lt;srcNodeConnector&gt;OF|2@OF|00:00:00:00:00:00:00:02&lt;/srcNodeConnector&gt;
+     * &lt;dstNodeConnector&gt;OF|2@OF|00:00:00:00:00:00:00:51&lt;/dstNodeConnector&gt;
+     * &lt;/topologyUserLinks&gt;
      *
      * Request in JSON:
      * {"status":"Success","name":"link1","srcNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:02","dstNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:51"}
      *
      * </pre>
      */
-    @Path("/{containerName}/user-link")
-    @POST
+    @Path("/{containerName}/userLink/{name}")
+    @PUT
     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
     @StatusCodes({
@@ -223,7 +313,8 @@ public class TopologyNorthboundJAXRS {
             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
     public Response addUserLink(
             @PathParam(value = "containerName") String containerName,
-            @TypeHint(TopologyUserLinkConfig.class) JAXBElement<TopologyUserLinkConfig> userLinkConfig) {
+            @PathParam(value = "name") String name,
+            @TypeHint(TopologyUserLinkConfig.class) TopologyUserLinkConfig userLinkConfig) {
 
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.WRITE, this)) {
@@ -238,9 +329,9 @@ public class TopologyNorthboundJAXRS {
                     RestMessages.NOCONTAINER.toString());
         }
 
-        Status status = topologyManager.addUserLink(userLinkConfig.getValue());
+        Status status = topologyManager.addUserLink(userLinkConfig);
         if (status.isSuccess()) {
-            NorthboundUtils.auditlog("User Link", username, "added", userLinkConfig.getValue().getName(), containerName);
+            NorthboundUtils.auditlog("User Link", username, "added", userLinkConfig.getName(), containerName);
             return Response.status(Response.Status.CREATED).build();
         }
         throw new InternalServerErrorException(status.getDescription());
@@ -260,16 +351,16 @@ public class TopologyNorthboundJAXRS {
      * Example:
      *
      * RequestURL:
-     * http://localhost:8080/controller/nb/v2/topology/default/user-link/config1
+     * http://localhost:8080/controller/nb/v2/topology/default/userLink/config1
      *
      * </pre>
      */
-    @Path("/{containerName}/user-link/{name}")
+    @Path("/{containerName}/userLink/{name}")
     @DELETE
     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
     @StatusCodes({
-            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 204, condition = "User link removed successfully"),
             @ResponseCode(code = 404, condition = "The Container Name or Link Configuration Name was not found"),
             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
     public Response deleteUserLink(
@@ -292,8 +383,8 @@ public class TopologyNorthboundJAXRS {
         Status ret = topologyManager.deleteUserLink(name);
         if (ret.isSuccess()) {
             NorthboundUtils.auditlog("User Link", username, "removed", name, containerName);
-            return Response.ok().build();
+            return Response.noContent().build();
         }
-        throw new ResourceNotFoundException(ret.getDescription());
+        return NorthboundUtils.getResponse(ret);
     }
 }