Swagger UI for AD-SAL 48/8048/2
authormrajvaid <mrajvaid@cisco.com>
Mon, 16 Jun 2014 19:59:21 +0000 (12:59 -0700)
committermrajvaid <mrajvaid@cisco.com>
Tue, 17 Jun 2014 21:48:56 +0000 (14:48 -0700)
 -Use 'mvn clean install -P docs' to build swagger ui bundle
 -UI can be accessed at  http://<controller-ip:contoller-web-port>/swagger

Change-Id: I466518f78e23d31c15515f3dcd1f3e46af802f2d
Signed-off-by: mrajvaid <mrajvaid@cisco.com>
opendaylight/distribution/opendaylight/pom.xml
opendaylight/northbound/swagger-ui/pom.xml [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/java/org/opendaylight/controller/swaggerui/BasePathModifierServlet.java [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/resources/css/custom.css [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/resources/images/logo.png [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/resources/index.html [new file with mode: 0644]
pom.xml

index 3916e05496ab2a40fc34e2adb71fd53839172ceb..7160acba8173fdf2e4981f84e44d877c8b830ce5 100644 (file)
         </plugins>
       </build>
     </profile>
+    <profile>
+      <id>docs</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>swagger-ui</artifactId>
+          <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+      </dependencies>
+    </profile>
   </profiles>
 </project>
diff --git a/opendaylight/northbound/swagger-ui/pom.xml b/opendaylight/northbound/swagger-ui/pom.xml
new file mode 100644 (file)
index 0000000..18eaed9
--- /dev/null
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+    <relativePath>../../commons/opendaylight</relativePath>
+  </parent>
+
+  <artifactId>swagger-ui</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <api.dir>${resource.dir}/apis</api.dir>
+    <resource.dir>${project.build.directory}/classes</resource.dir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.google.code.gson</groupId>
+      <artifactId>gson</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>javax.servlet</artifactId>
+    </dependency>
+    <!-- add dependency on all northbound bundles -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>connectionmanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>controllermanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>flowprogrammer.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>forwarding.staticrouting.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>networkconfig.bridgedomain.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>statistics.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>subnets.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>switchmanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>topology.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>usermanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Export-Package></Export-Package>
+            <Import-Package>org.slf4j,
+              javax.annotation,
+              javax.naming,
+              javax.servlet,
+              javax.servlet.annotation,
+              javax.servlet.http,
+              com.google.gson,</Import-Package>
+            <Export-Package></Export-Package>
+            <Include-Resource>apis=target/classes/apis,
+                index.html=target/classes/index.html,
+                apilist.json=target/classes/apilist.json,
+                css=target/classes/css,
+                lib=target/classes/lib,
+                swagger-ui.min.js=target/classes/swagger-ui.min.js,
+                swagger-ui.js=target/classes/swagger-ui.js,
+                images=target/classes/images,
+                WEB-INF/web.xml=target/classes/WEB-INF/web.xml</Include-Resource>
+            <Web-ContextPath>/swagger</Web-ContextPath>
+          </instructions>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <version>1.7</version>
+        <dependencies>
+          <dependency>
+            <groupId>ant-contrib</groupId>
+            <artifactId>ant-contrib</artifactId>
+            <version>1.0b3</version>
+            <exclusions>
+              <exclusion>
+                <groupId>ant</groupId>
+                <artifactId>ant</artifactId>
+              </exclusion>
+            </exclusions>
+          </dependency>
+        </dependencies>
+        <executions>
+          <execution>
+            <goals>
+              <goal>run</goal>
+            </goals>
+            <phase>generate-sources</phase>
+            <configuration>
+              <target>
+                <taskdef classpathref="maven.plugin.classpath" resource="net/sf/antcontrib/antlib.xml"></taskdef>
+                <patternset id="rest.paths">
+                  <include name="**/enunciate/generate/swagger/ui/*.json"></include>
+                  <exclude name="**/java-client/**"></exclude>
+                  <exclude name="**/swagger-ui/**"></exclude>
+                </patternset>
+
+                <echo message="======== Assembling swagger docs ========"></echo>
+                <!-- make api directory -->
+                <mkdir dir="${api.dir}"></mkdir>
+                <!--  copy swagger libs -->
+                <copy todir="${resource.dir}">
+                  <fileset dir="../subnets/target/enunciate/generate/swagger/ui">
+                    <exclude name="**/*.json"></exclude>
+                    <exclude name="**/*.png"></exclude>
+                    <exclude name="**/index.html"></exclude>
+                  </fileset>
+                </copy>
+                <!--  Copy NorthBound json files into ui directory-->
+                <copy todir="${api.dir}">
+                  <fileset dir="${basedir}/../../..">
+                    <patternset refid="rest.paths"></patternset>
+                  </fileset>
+                  <mapper>
+                    <regexpmapper from="^(.*)/([^/]+)/*/target/enunciate/generate/swagger/ui/(.*Northbound).*$$" to="\3"></regexpmapper>
+                    <regexpmapper from="^(.*)/([^/]+)/*/target/enunciate/generate/swagger/ui/(.*resource-list.json)$$" to="\2-\3"></regexpmapper>
+                  </mapper>
+                </copy>
+
+                <!--  Correct base path -->
+                <replaceregexp match="/full" replace="">
+                  <fileset dir="${api.dir}">
+                    <include name="**/*Northbound"></include>
+                  </fileset>
+                </replaceregexp>
+                <!--  Merge Resource list -->
+                <echo append="false" file="${resource.dir}/apilist.json">{
+  "swaggerVersion": "1.1",
+  "basePath": "http://localhost:8080/swagger/apis",
+  "apis": [</echo>
+                <for param="file">
+                  <path>
+                    <fileset dir="${api.dir}">
+                      <include name="**/*resource-list.json"></include>
+                      <exclude name="**/neutron*"></exclude>
+                    </fileset>
+                  </path>
+                  <sequential>
+                    <echo message="Processing json resource @{file}"></echo>
+                    <loadfile property="jsoncontent" srcfile="@{file}">
+                      <filterchain>
+                        <headfilter lines="10"></headfilter>
+                        <tailfilter lines="6"></tailfilter>
+                      </filterchain>
+                    </loadfile>
+                    <echo append="true" file="${resource.dir}/apilist.json" message="${jsoncontent},"></echo>
+                    <var name="jsoncontent" unset="true"></var>
+                  </sequential>
+                </for>
+                <sequential>
+                  <loadfile property="jsoncontent" srcfile="${api.dir}/neutron-resource-list.json">
+                    <filterchain>
+                      <headfilter lines="46"></headfilter>
+                      <tailfilter lines="42"></tailfilter>
+                    </filterchain>
+                  </loadfile>
+                  <echo append="true" file="${resource.dir}/apilist.json" message="${jsoncontent},"></echo>
+                  <var name="jsoncontent" unset="true"></var>
+                </sequential>
+                <echo append="true" file="${resource.dir}/apilist.json">{ }
+  ]
+}</echo>
+
+                <!-- Remove .json from api paths -->
+                <replaceregexp file="${resource.dir}/apilist.json" flags="g" match=".json" replace=""></replaceregexp>
+                <replaceregexp file="${resource.dir}/apilist.json" flags="g" match="JAXRS" replace=""></replaceregexp>
+
+                <!-- cleanup resource files as we don't need them -->
+                <delete>
+                  <fileset dir="${api.dir}" includes="**/*resource-list.json"></fileset>
+                </delete>
+                <echo message="======== Build successful ========"></echo>
+              </target>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+  </scm>
+</project>
diff --git a/opendaylight/northbound/swagger-ui/src/main/java/org/opendaylight/controller/swaggerui/BasePathModifierServlet.java b/opendaylight/northbound/swagger-ui/src/main/java/org/opendaylight/controller/swaggerui/BasePathModifierServlet.java
new file mode 100644 (file)
index 0000000..083a50c
--- /dev/null
@@ -0,0 +1,101 @@
+package org.opendaylight.controller.swaggerui;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+/**
+ * Servlet implementation class BasePathModifierServlet
+ */
+public class BasePathModifierServlet extends HttpServlet {
+    private static final long serialVersionUID = 1L;
+    private static final Logger logger = LoggerFactory
+            .getLogger(BasePathModifierServlet.class);
+
+    private static final String API_BASE_PATH_SUFFIX = "/swagger/apis";
+    private static final String BASE_PATH_KEY = "basePath";
+
+    /**
+     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
+     *      response)
+     */
+    @Override
+    protected void doGet(HttpServletRequest request,
+            HttpServletResponse response) throws ServletException, IOException {
+        String resourcePath = request.getRequestURI().substring(
+                request.getContextPath().length());
+        logger.debug("Locating resource : {}.", resourcePath);
+        JsonObject jsonObject = null;
+        try {
+
+            InputStream stream = this.getServletContext().getResourceAsStream(
+                    resourcePath);
+            if (stream == null) {
+                response.sendError(HttpServletResponse.SC_NOT_FOUND,
+                        "API / API Listing not found");
+                return;
+            }
+            BufferedReader streamReader = new BufferedReader(
+                    new InputStreamReader(stream, "UTF-8"));
+            StringBuilder responseStrBuilder = new StringBuilder();
+
+            String inputStr;
+            while ((inputStr = streamReader.readLine()) != null)
+                responseStrBuilder.append(inputStr);
+
+            JsonElement jelement = new JsonParser().parse(responseStrBuilder
+                    .toString());
+            jsonObject = jelement.getAsJsonObject();
+
+            String basePath = jsonObject.get(BASE_PATH_KEY).getAsString();
+
+            // construct base path
+            StringBuilder requestURL = new StringBuilder();
+
+            requestURL.append(request.isSecure() ? "https://" : "http://")
+                    .append(request.getServerName()).append(":")
+                    .append(request.getServerPort());
+            if (!basePath.contains(requestURL)) {
+                String endPath = "";
+                if (basePath.contains(API_BASE_PATH_SUFFIX)) {
+                    endPath = basePath.substring(basePath
+                            .indexOf(API_BASE_PATH_SUFFIX));
+                }
+                basePath = requestURL + endPath;
+                logger.debug("Modified Base Path is {}", basePath);
+                jsonObject.addProperty(BASE_PATH_KEY, basePath);
+            }
+        } catch (Exception ex) {
+            logger.error("Error processing JSON data", ex);
+            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                    "Could not read API Listing or APIs");
+            return;
+        }
+
+        try {
+            response.setContentType("application/json");
+            PrintWriter out = response.getWriter();
+            out.print(jsonObject);
+            out.flush();
+        } catch (Exception ex) {
+            logger.error("Error while writing response", ex);
+            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                    "Internal Error while writing resposne");
+        }
+    }
+
+}
diff --git a/opendaylight/northbound/swagger-ui/src/main/resources/WEB-INF/web.xml b/opendaylight/northbound/swagger-ui/src/main/resources/WEB-INF/web.xml
new file mode 100644 (file)
index 0000000..6d02390
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+         version="3.0">
+  <servlet>
+     <servlet-name>BasePathModifierServlet</servlet-name>
+     <servlet-class>org.opendaylight.controller.swaggerui.BasePathModifierServlet</servlet-class>
+  </servlet>
+  <!-- Mapping for all northbound json files aka apis-->
+  <servlet-mapping>
+    <servlet-name>BasePathModifierServlet</servlet-name>
+    <url-pattern>/apis/*</url-pattern>
+  </servlet-mapping>
+  <!-- Mapping to get list of available NB apis -->
+  <servlet-mapping>
+    <servlet-name>BasePathModifierServlet</servlet-name>
+    <url-pattern>/apilist.json</url-pattern>
+  </servlet-mapping>
+  <welcome-file-list>
+    <welcome-file>index.html</welcome-file>
+  </welcome-file-list>
+</web-app>
diff --git a/opendaylight/northbound/swagger-ui/src/main/resources/css/custom.css b/opendaylight/northbound/swagger-ui/src/main/resources/css/custom.css
new file mode 100644 (file)
index 0000000..e393943
--- /dev/null
@@ -0,0 +1,12 @@
+body #header a#logo {
+    font-size: 1.5em;
+    font-weight: bold;
+    text-decoration: none;
+    background: transparent url(../images/logo.png) no-repeat left center;
+    padding: 20px 0 20px 70px;
+    color: white;
+}
+
+div.footer {
+    display: none;
+}
diff --git a/opendaylight/northbound/swagger-ui/src/main/resources/images/logo.png b/opendaylight/northbound/swagger-ui/src/main/resources/images/logo.png
new file mode 100644 (file)
index 0000000..d49fb86
Binary files /dev/null and b/opendaylight/northbound/swagger-ui/src/main/resources/images/logo.png differ
diff --git a/opendaylight/northbound/swagger-ui/src/main/resources/index.html b/opendaylight/northbound/swagger-ui/src/main/resources/index.html
new file mode 100644 (file)
index 0000000..bb5126c
--- /dev/null
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Swagger UI</title>
+    <link href='//fonts.googleapis.com/css?family=Droid+Sans:400,700' rel='stylesheet' type='text/css'/>
+    <link href='css/highlight.default.css' media='screen' rel='stylesheet' type='text/css'/>
+    <link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
+    <link href='css/custom.css' media='screen' rel='stylesheet' type='text/css'/>
+    <script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>
+    <script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
+    <script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
+    <script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
+    <script src='lib/handlebars-1.0.rc.1.js' type='text/javascript'></script>
+    <script src='lib/underscore-min.js' type='text/javascript'></script>
+    <script src='lib/backbone-min.js' type='text/javascript'></script>
+    <script src='lib/swagger.js' type='text/javascript'></script>
+    <script src='swagger-ui.js' type='text/javascript'></script>
+    <script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
+
+    <script type="text/javascript">
+    $(function () {
+        window.swaggerUi = new SwaggerUi({
+                discoveryUrl:"./apilist.json",
+                apiKey:"",
+                dom_id:"swagger-ui-container",
+                supportHeaderParams: false,
+                supportedSubmitMethods: ['get', 'post', 'put', 'delete'],
+                onComplete: function(swaggerApi, swaggerUi){
+                    if(console) {
+                        console.log("Loaded SwaggerUI")
+                        console.log(swaggerApi);
+                        console.log(swaggerUi);
+                    }
+                  $('pre code').each(function(i, e) {hljs.highlightBlock(e)});
+                },
+                onFailure: function(data) {
+                    if(console) {
+                        console.log("Unable to Load SwaggerUI");
+                        console.log(data);
+                    }
+                },
+                docExpansion: "none"
+            });
+
+            window.swaggerUi.load();
+        });
+
+    </script>
+</head>
+
+<body>
+  <div id='header'>
+    <div class="swagger-ui-wrap">
+      <a id="logo" href="http://www.opendaylight.org/">ODL NB API</a>
+      <form id='api_selector'>
+        <div class='input'>
+          <input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text"/>
+        </div>
+        <div class='input'>
+          <input placeholder="api_key" id="input_apiKey" name="apiKey" type="text"/>
+        </div>
+        <div class='input'><a id="explore" href="#">Explore</a></div>
+      </form>
+    </div>
+  </div>
+
+  <div id="message-bar" class="swagger-ui-wrap">
+      &nbsp;
+  </div>
+
+  <div id="swagger-ui-container" class="swagger-ui-wrap">
+
+  </div>
+
+</body>
+
+</html>
diff --git a/pom.xml b/pom.xml
index a26533819c45e8a8a89d696eef00093551db1b49..c54d9a930f28ad39ad680f30314508248bd2eea5 100644 (file)
--- a/pom.xml
+++ b/pom.xml
       </activation>
       <modules>
         <module>opendaylight/northbound/java-client</module>
+        <module>opendaylight/northbound/swagger-ui</module>
       </modules>
     </profile>
   </profiles>