All Downloads are FREE. Search and download functionalities are using the official Maven repository.

play.modules.swagger.SwaggerPlugin.scala Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2019 SmartBear Software, Inc.
 *
 * Licensed 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 play.modules.swagger

import java.io.File
import javax.inject.Inject
import io.swagger.config.{FilterFactory, ScannerFactory}
import play.modules.swagger.util.SwaggerContext
import io.swagger.core.filter.SwaggerSpecFilter
import play.api.inject.ApplicationLifecycle
import play.api.{Logger, Application}
import play.api.routing.Router
import scala.concurrent.Future
import scala.collection.JavaConverters._
import play.routes.compiler.{Route => PlayRoute, Include => PlayInclude, RoutesFileParser, StaticPart}

import scala.io.Source

trait SwaggerPlugin

class SwaggerPluginImpl @Inject()(lifecycle: ApplicationLifecycle, router: Router, app: Application) extends SwaggerPlugin {

  val logger = Logger("swagger")

  val config = app.configuration
  logger.info("Swagger - starting initialisation...")

  val apiVersion = config.getOptional[String]("api.version") match {
    case None => "beta"
    case Some(value) => value
  }

  val basePath = config.getOptional[String]("swagger.api.basepath")
    .filter(path => !path.isEmpty)
    .getOrElse("/")

  val host = config.getOptional[String]("swagger.api.host")
    .filter(host => !host.isEmpty)
    .getOrElse("localhost:9000")

  val title = config.getOptional[String]("swagger.api.info.title") match {
    case None => ""
    case Some(value)=> value
  }

  val description = config.getOptional[String]("swagger.api.info.description") match {
    case None => ""
    case Some(value)=> value
  }

  val termsOfServiceUrl = config.getOptional[String]("swagger.api.info.termsOfServiceUrl") match {
    case None => ""
    case Some(value)=> value
  }

  val contact = config.getOptional[String]("swagger.api.info.contact") match {
    case None => ""
    case Some(value)=> value
  }

  val license = config.getOptional[String]("swagger.api.info.license") match {
    case None => ""
    case Some(value)=> value
  }

  val licenseUrl = config.getOptional[String]("swagger.api.info.licenseUrl") match {
    // licenceUrl needs to be a valid URL to validate against schema
    case None => "http://licenseUrl"
    case Some(value)=> value
  }

  SwaggerContext.registerClassLoader(app.classloader)

  var scanner = new PlayApiScanner()
  ScannerFactory.setScanner(scanner)

  var swaggerConfig = new PlaySwaggerConfig()

  swaggerConfig.description = description
  swaggerConfig.basePath = basePath
  swaggerConfig.contact = contact
  swaggerConfig.version = apiVersion
  swaggerConfig.title = title
  swaggerConfig.host = host
  swaggerConfig.termsOfServiceUrl = termsOfServiceUrl
  swaggerConfig.license = license
  swaggerConfig.licenseUrl = licenseUrl

  PlayConfigFactory.setConfig(swaggerConfig)


  val routes = parseRoutes

  def parseRoutes: List[PlayRoute] = {
    def playRoutesClassNameToFileName(className: String) = className.replace(".Routes", ".routes")

    val routesFile = if (config.underlying.hasPath("play.http.router")) {
      config.getOptional[String]("play.http.router") match {
        case None => "routes"
        case Some(value) => playRoutesClassNameToFileName(value)
      }
    } else {
      "routes"
    }
    //Parses multiple route files recursively
    def parseRoutesHelper(routesFile: String, prefix: String): List[PlayRoute] = {
      logger.debug(s"Processing route file '$routesFile' with prefix '$prefix'")

      val routesContent =  Source.fromInputStream(app.classloader.getResourceAsStream(routesFile)).mkString
      val parsedRoutes = RoutesFileParser.parseContent(routesContent,new File(routesFile))
      val routes = parsedRoutes.right.get.collect {
        case route: PlayRoute =>
          logger.debug(s"Adding route '$route'")
          Seq(route.copy(path = route.path.copy(parts = StaticPart(prefix) +: route.path.parts)))
        case include: PlayInclude =>
          logger.debug(s"Processing route include $include")
          parseRoutesHelper(playRoutesClassNameToFileName(include.router), include.prefix)
      }.flatten
      logger.debug(s"Finished processing route file '$routesFile'")
      routes
    }
    parseRoutesHelper(routesFile, "")
  }

  val routesRules = routes.map(route => s"${route.call.packageName.map(_ + ".").getOrElse("")}${route.call.controller}$$.${route.call.method}" -> route).toMap

  val route = new RouteWrapper(routesRules.asJava)
  RouteFactory.setRoute(route)
  app.configuration.getOptional[String]("swagger.filter") match {
    case Some(e) if e != "" =>
      try {
        FilterFactory setFilter SwaggerContext.loadClass(e).newInstance.asInstanceOf[SwaggerSpecFilter]
        logger.debug("Setting swagger.filter to %s".format(e))
      }
      catch {
        case ex: Exception => Logger("swagger").error("Failed to load filter " + e, ex)
      }
    case _ =>
  }

  val docRoot = ""
  ApiListingCache.listing(docRoot, "127.0.0.1")

  logger.info("Swagger - initialization done.")

  // previous contents of Plugin.onStart
  lifecycle.addStopHook { () =>
    ApiListingCache.cache = None
    logger.info("Swagger - stopped.")

    Future.successful(())
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy