Rest DSL. camel-swagger work in progress.

Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/b234476a
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/b234476a
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/b234476a

Branch: refs/heads/master
Commit: b234476abf46ddf1f109fe3fbc1b6395c0ae5228
Parents: a578af9
Author: Claus Ibsen <davscl...@apache.org>
Authored: Sat Aug 9 11:51:52 2014 +0200
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Sat Aug 9 12:31:18 2014 +0200

----------------------------------------------------------------------
 .../component/swagger/RestApiListingCache.scala |  54 +++++++++
 .../RestSwaggerApiDeclarationServlet.scala      | 117 +++++++++++++------
 .../component/swagger/RestSwaggerReader.scala   |  30 ++---
 .../src/main/webapp/WEB-INF/web.xml             |  34 +++---
 4 files changed, 164 insertions(+), 71 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/b234476a/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestApiListingCache.scala
----------------------------------------------------------------------
diff --git 
a/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestApiListingCache.scala
 
b/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestApiListingCache.scala
new file mode 100644
index 0000000..494e620
--- /dev/null
+++ 
b/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestApiListingCache.scala
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.camel.component.swagger
+
+import com.wordnik.swagger.core.util.ReaderUtil
+import com.wordnik.swagger.config.SwaggerConfig
+import org.apache.camel.CamelContext
+import com.wordnik.swagger.model.{Operation, ApiListing}
+import scala.collection.mutable.ListBuffer
+
+// to iterate Java list using for loop
+import scala.collection.JavaConverters._
+
+object RestApiListingCache extends ReaderUtil {
+
+  var cache: Option[Map[String, ApiListing]] = None
+  val reader = new RestSwaggerReader()
+
+  def listing(camel: CamelContext, config: SwaggerConfig): Option[Map[String, 
ApiListing]] = {
+    cache.orElse {
+      val listings = new ListBuffer[ApiListing]
+
+      val rests = camel.getRestDefinitions.asScala
+      for (rest <- rests) {
+        // TODO: this can be nicer
+        val option = reader.read(rest, config)
+        if (option.get != null) {
+          listings += option.get
+        }
+      }
+
+      if (listings.size > 0) {
+        val mergedListings = groupByResourcePath(listings.toList)
+        cache = Some(mergedListings.map(m => (m.resourcePath, m)).toMap)
+      }
+      cache
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/b234476a/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestSwaggerApiDeclarationServlet.scala
----------------------------------------------------------------------
diff --git 
a/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestSwaggerApiDeclarationServlet.scala
 
b/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestSwaggerApiDeclarationServlet.scala
index 0cb985f..11af449 100644
--- 
a/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestSwaggerApiDeclarationServlet.scala
+++ 
b/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestSwaggerApiDeclarationServlet.scala
@@ -16,55 +16,99 @@
  */
 package org.apache.camel.component.swagger
 
-import com.wordnik.swagger.servlet.listing.{ApiListingCache, 
ApiDeclarationServlet}
-import javax.servlet.http.{HttpServletResponse, HttpServletRequest}
+import javax.servlet.http.{HttpServlet, HttpServletResponse, 
HttpServletRequest}
+import javax.servlet.ServletConfig
+
+import com.wordnik.swagger.core.SwaggerContext
 import com.wordnik.swagger.core.filter.SpecFilter
-import com.wordnik.swagger.config.{ConfigFactory, FilterFactory}
-import com.wordnik.swagger.model.{ResourceListing, ApiListingReference}
 import com.wordnik.swagger.core.util.JsonSerializer
-import javax.servlet.ServletConfig
+import com.wordnik.swagger.config.{SwaggerConfig, ConfigFactory, FilterFactory}
+import com.wordnik.swagger.model.{ApiInfo, ResourceListing, 
ApiListingReference}
+
 import org.springframework.web.context.support.WebApplicationContextUtils
 import org.springframework.web.context.WebApplicationContext
 import org.apache.camel.CamelContext
 import org.slf4j.LoggerFactory
 
-class RestSwaggerApiDeclarationServlet extends ApiDeclarationServlet {
+class RestSwaggerApiDeclarationServlet extends HttpServlet {
+
+  // TODO: this has spring dependency, find a way to make it work with 
blueprint/spring/cdi/servlet-listener etc
 
   private val LOG = 
LoggerFactory.getLogger(classOf[RestSwaggerApiDeclarationServlet])
 
   var spring: WebApplicationContext = null
   val reader = new RestSwaggerReader()
+  var camel: CamelContext = null
+  val swaggerConfig: SwaggerConfig = ConfigFactory.config
 
   override def init(config: ServletConfig): Unit = {
     super.init(config)
     LOG.info("init")
+
+    // configure swagger options
+    var s = config.getInitParameter("api.version")
+    if (s != null) {
+      swaggerConfig.setApiVersion(s)
+    }
+    s = config.getInitParameter("swagger.version")
+    if (s != null) {
+      swaggerConfig.setSwaggerVersion(s)
+    }
+    s = config.getInitParameter("base.path")
+    if (s != null) {
+      swaggerConfig.setBasePath(s)
+    }
+    s = config.getInitParameter("api.path")
+    if (s != null) {
+      swaggerConfig.setApiPath(s)
+    }
+
+    val title = config.getInitParameter("api.title")
+    val description = config.getInitParameter("api.description")
+    val termsOfServiceUrl = config.getInitParameter("api.termsOfServiceUrl")
+    val contact = config.getInitParameter("api.contact")
+    val license = config.getInitParameter("api.license")
+    val licenseUrl = config.getInitParameter("api.licenseUrl")
+
+    val apiInfo = new ApiInfo(title, description, termsOfServiceUrl, contact, 
license, licenseUrl)
+    swaggerConfig.setApiInfo(apiInfo)
+
     spring = 
WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext)
+    if (spring != null) {
+      camel = spring.getBean(classOf[CamelContext])
+      if (camel != null) {
+        // TODO: if this is not sufficient we need to use Camel's resolveClass 
API instead
+        
SwaggerContext.registerClassLoader(camel.getApplicationContextClassLoader)
+      }
+    }
+
     LOG.info("init found spring {}", spring)
   }
 
-  override def renderResourceListing(request: HttpServletRequest, response: 
HttpServletResponse) = {
+  override protected def doGet(request: HttpServletRequest, response: 
HttpServletResponse) = {
+    val route = request.getPathInfo
+    // render overview if the route is empty or is the root path
+    if (route != null && route != "" && route != "/") {
+      renderApiDeclaration(request, response)
+    } else {
+      renderResourceListing(request, response)
+    }
+  }
+
+  /**
+   * Renders the resource listing which is the overview of all the apis
+   */
+  def renderResourceListing(request: HttpServletRequest, response: 
HttpServletResponse) = {
     LOG.info("renderResourceListing")
 
-    val docRoot = ""
     val queryParams = Map[String, List[String]]()
     val cookies = Map[String, String]()
     val headers = Map[String, List[String]]()
 
-    val camel = spring.getBean(classOf[CamelContext])
     LOG.info("renderResourceListing camel -> {}", camel)
     if (camel != null) {
-
-      val config = ConfigFactory.config
-      val rests = camel.getRestDefinitions
-      LOG.info("renderResourceListing rests -> {}", rests)
-      val list = reader.read(rests.get(0), config)
-      LOG.info("renderResourceListing reader -> {}", list)
-      val cache = Some(list.map(m => (m.resourcePath, m)).toMap)
-      LOG.info("renderResourceListing reader -> {}", cache)
-
       val f = new SpecFilter
-      // val listings = ApiListingCache.listing(docRoot).map(specs => {
-      val listings = cache.map(specs => {
+      val listings = RestApiListingCache.listing(camel, 
swaggerConfig).map(specs => {
         (for (spec <- specs.values)
         yield f.filter(spec, FilterFactory.filter, queryParams, cookies, 
headers)
           ).filter(m => m.apis.size > 0)
@@ -72,16 +116,24 @@ class RestSwaggerApiDeclarationServlet extends 
ApiDeclarationServlet {
       val references = (for (listing <- listings.getOrElse(List())) yield {
         ApiListingReference(listing.resourcePath, listing.description)
       }).toList
-      val resourceListing = ResourceListing(config.apiVersion,
-        config.swaggerVersion,
-        references
+      val resourceListing = ResourceListing(
+        swaggerConfig.apiVersion,
+        swaggerConfig.swaggerVersion,
+        references,
+        List(),
+        swaggerConfig.info
       )
       LOG.info("renderResourceListing write response -> {}", resourceListing)
       
response.getOutputStream.write(JsonSerializer.asJson(resourceListing).getBytes("utf-8"))
+    } else {
+      response.setStatus(204)
     }
   }
 
-  override def renderApiDeclaration(request: HttpServletRequest, response: 
HttpServletResponse) = {
+  /**
+   * Renders the api listing of a single resource
+   */
+  def renderApiDeclaration(request: HttpServletRequest, response: 
HttpServletResponse) = {
     val route = request.getPathInfo
     val docRoot = request.getPathInfo
     val f = new SpecFilter
@@ -90,20 +142,9 @@ class RestSwaggerApiDeclarationServlet extends 
ApiDeclarationServlet {
     val headers = Map[String, List[String]]()
     val pathPart = docRoot
 
-    val camel = spring.getBean(classOf[CamelContext])
     LOG.info("renderApiDeclaration camel -> {}", camel)
     if (camel != null) {
-
-      val config = ConfigFactory.config
-      val rests = camel.getRestDefinitions
-      LOG.info("renderApiDeclaration rests -> {}", rests)
-      val list = reader.read(rests.get(0), config)
-      LOG.info("renderApiDeclaration reader -> {}", list)
-      val cache = Some(list.map(m => (m.resourcePath, m)).toMap)
-      LOG.info("renderApiDeclaration reader -> {}", cache)
-
-      // val listings = ApiListingCache.listing(docRoot).map(specs => {
-      val listings = cache.map(specs => {
+      val listings = RestApiListingCache.listing(camel, 
swaggerConfig).map(specs => {
           (for (spec <- specs.values) yield {
           f.filter(spec, FilterFactory.filter, queryParams, cookies, headers)
         }).filter(m => m.resourcePath == pathPart)
@@ -115,8 +156,10 @@ class RestSwaggerApiDeclarationServlet extends 
ApiDeclarationServlet {
         }
         case _ => response.setStatus(404)
       }
+    } else {
+      // no data
+      response.setStatus(204)
     }
-    response.setStatus(404)
   }
 
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/b234476a/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestSwaggerReader.scala
----------------------------------------------------------------------
diff --git 
a/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestSwaggerReader.scala
 
b/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestSwaggerReader.scala
index 2b57013..39f0f56 100644
--- 
a/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestSwaggerReader.scala
+++ 
b/components/camel-swagger/src/main/scala/org/apache/camel/component/swagger/RestSwaggerReader.scala
@@ -6,7 +6,7 @@
  * (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
+ *      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,
@@ -48,6 +48,8 @@ class RestSwaggerReader {
     }
   }
 
+  // TOOD: register classloader
+
   def read(rest: RestDefinition, config: SwaggerConfig): Option[ApiListing] = {
 
     val resourcePath = rest.getPath
@@ -87,20 +89,12 @@ class RestSwaggerReader {
         case _ => "java.lang.Void"
       }
 
-      var p = verb.getProduces
-      if (p == null) {
-        p = rest.getProduces
-      }
-      val produces = p match {
+      val produces = verb.getProduces match {
         case e: String if e != "" => e.split(",").map(_.trim).toList
         case _ => List()
       }
 
-      var c = verb.getConsumes
-      if (c == null) {
-        c = rest.getConsumes
-      }
-      val consumes = c match {
+      val consumes = verb.getConsumes match {
         case e: String if e != "" => e.split(",").map(_.trim).toList
         case _ => List()
       }
@@ -131,6 +125,16 @@ class RestSwaggerReader {
 
     if (apis.size > 0) {
 
+      val produces = rest.getProduces match {
+        case e: String if e != "" => e.split(",").map(_.trim).toList
+        case _ => List()
+      }
+
+      val consumes = rest.getConsumes match {
+        case e: String if e != "" => e.split(",").map(_.trim).toList
+        case _ => List()
+      }
+
       val models = ModelUtil.modelsFromApis(apis.toList)
       Some(
         ApiListing(
@@ -138,8 +142,8 @@ class RestSwaggerReader {
           SwaggerSpec.version,
           config.basePath,
           resourcePath,
-          List(), // produces
-          List(), // consumes
+          produces,
+          consumes,
           List(), // protocols
           List(), // authorizations
           ModelUtil.stripPackages(apis.toList),

http://git-wip-us.apache.org/repos/asf/camel/blob/b234476a/examples/camel-example-servlet-rest-tomcat/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git 
a/examples/camel-example-servlet-rest-tomcat/src/main/webapp/WEB-INF/web.xml 
b/examples/camel-example-servlet-rest-tomcat/src/main/webapp/WEB-INF/web.xml
index 0833518..e0c8151 100755
--- a/examples/camel-example-servlet-rest-tomcat/src/main/webapp/WEB-INF/web.xml
+++ b/examples/camel-example-servlet-rest-tomcat/src/main/webapp/WEB-INF/web.xml
@@ -39,26 +39,6 @@
     
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>
 
-
-  <!-- swagger servlet reader -->
-  <servlet>
-    <servlet-name>DefaultServletReaderConfig</servlet-name>
-    
<servlet-class>com.wordnik.swagger.servlet.config.DefaultServletReaderConfig</servlet-class>
-    <load-on-startup>1</load-on-startup>
-    <init-param>
-      <param-name>swagger.resource.package</param-name>
-      <param-value>org.apache.camel.example.rest</param-value>
-    </init-param>
-    <init-param>
-      <param-name>swagger.api.basepath</param-name>
-      <param-value>http://localhost:8082</param-value>
-    </init-param>
-    <init-param>
-      <param-name>api.version</param-name>
-      <param-value>1.0.1</param-value>
-    </init-param>
-  </servlet>
-
   <!-- to setup Camel Servlet -->
   <servlet>
     <servlet-name>CamelServlet</servlet-name>
@@ -67,11 +47,23 @@
     <load-on-startup>3</load-on-startup>
   </servlet>
 
+  <!-- to setup Camel Swagger api servlet -->
   <servlet>
     <servlet-name>ApiDeclarationServlet</servlet-name>
-    
<!--<servlet-class>com.wordnik.swagger.servlet.listing.ApiDeclarationServlet</servlet-class>-->
     
<servlet-class>org.apache.camel.component.swagger.RestSwaggerApiDeclarationServlet</servlet-class>
     <load-on-startup>2</load-on-startup>
+    <init-param>
+      <param-name>swagger.api.basepath</param-name>
+      <param-value>http://localhost:8080/api-docs</param-value>
+    </init-param>
+    <init-param>
+      <param-name>api.version</param-name>
+      <param-value>1.2.3</param-value>
+    </init-param>
+    <init-param>
+      <param-name>api.title</param-name>
+      <param-value>Camel Rest Example with Swagger</param-value>
+    </init-param>
   </servlet>
 
   <!-- define that url path for the Camel Servlet to use -->

Reply via email to