aboutsummaryrefslogblamecommitdiff
path: root/tools/gui/src/Main.scala
blob: 3b4bd909938b1dae366358fd55e163fb935f8067 (plain) (tree)
1
2
3
4
5
6
7

                                     
                          
 


                                                



















                                                                                                          



                                                                                 

                                               
                                        







                                                                                                                      




                                                                        
                                    

                         






                                                                                             



















                                                                                                           






                                                          
           




                                                                      


                                                                                        



































                                                                          







                                                                                                 






                                                 







                                                                                                       

     

                                                                                                  
 
 
import java.io.{File, IOException}
import java.net.MalformedURLException
import java.nio.file.Files

import org.commonmark.parser.Parser
import org.commonmark.renderer.html.HtmlRenderer

import scala.io.Source
import scala.util.{Failure, Success, Try}
import scalaj.http.Http

object Main {

  private val maven_host = "search.maven.org"
  private val cbt_home = System.getenv("CBT_HOME")

  implicit class StringExtensionMethods(str: String) {
    def /(s: String): String = str + File.separator + s
  }

  val uiPort = 9080

  def main(args: Array[String]) = launchUi(new File(args(0)), args(1))

  def launchUi(projectDirectory: File, scalaMajorVersion: String): Unit = {
    val staticBase = new File(cbt_home / "tools" / "gui" / "resources" / "web").toURI.toURL.toExternalForm
    val server = new JettyServer(uiPort, staticBase) {
      override def route(method: String,
                         path: String,
                         param: String => String,
                         setContentType: String => Unit) = (method, path) match {
        case ("GET", "/cwd") =>
          Success(s"""["$projectDirectory"]""")
        case ("POST", "/project/new") =>
          val name = param("name")
          val defaultPackage = param("pack")
          val dependencies = param("dependencies")
          val flags = param("flags")
          handleIoException {
            new ProjectBuilder(name, defaultPackage, dependencies, flags, projectDirectory, scalaMajorVersion).build()
            Success("[]")
          }
        case ("POST", "/project/copy") =>
          val name = param("name")
          val source = new File(cbt_home / "examples" / name)
          val target = new File(projectDirectory.getAbsolutePath / name)
          handleIoException {
            copyTree(source, target)
            Success("[]")
          }
        case ("GET", "/dependency") =>
          val query = param("query")
          handleIoException(handleMavenBadResponse(searchDependency(query)))
        case ("GET", "/dependency/version") =>
          val group = param("group")
          val artifact = param("artifact")
          handleIoException(handleMavenBadResponse(searchDependencyVersion(group, artifact)))
        case ("GET", "/examples") =>
          handleIoException {
            val names = new File(cbt_home / "examples").listFiles().filter(_.isDirectory).sortBy(_.getName)
                .map('"' + _.getName + '"').mkString(",")
            Success(s"[$names]")
          }
        case ("GET", "/example/files") =>
          val name = param("name")
          handleIoException {
            val dir = new File(cbt_home / "examples" / name)
            if (dir.exists())
              Success(serializeTree(dir))
            else
              Failure(new IllegalArgumentException(s"Incorrect example name: $name"))
          }
        case ("GET", "/example/file") =>
          setContentType("text/plain")
          val path = param("path")
          handleIoException {
            val file = new File(path)
            Success {
              val content = Source.fromFile(file).mkString
              if (file.getName.endsWith(".md"))
                parseMd(content)
              else
                content
            }
          }
        case _ =>
          Failure(new MalformedURLException(s"Incorrect path: $path"))
      }
    }
    server.start()
    if(!java.awt.GraphicsEnvironment.isHeadless()) {
      java.awt.Desktop.getDesktop.browse(new java.net.URI(s"http://localhost:$uiPort/"))
    }

    println("Press Enter to stop UI server.")
    while (Source.stdin.getLines().next().nonEmpty) {}
    server.stop()
  }

  private def searchDependency(query: String) = {
    Http(s"http://$maven_host/solrsearch/select")
        .param("q", query)
        .param("rows", "30")
        .param("wt", "json")
        .asString.body
  }

  private def searchDependencyVersion(group: String, artifact: String) = {
    val query = s"""q=g:"$group"+AND+a:"$artifact""""
    Http(s"http://$maven_host/solrsearch/select?" + query)
        .param("rows", "30")
        .param("wt", "json")
        .param("core", "gav")
        .asString.body
  }

  private def handleIoException(f: => Try[String]) = try f catch {
    case e: IOException =>
      e.printStackTrace()
      Failure(e)
  }

  private def handleMavenBadResponse(result: String) = {
    if (result.startsWith("{"))
      Success(result)
    else
      Failure(new Exception(s"Bad response from $maven_host: $result"))
  }

  private def serializeTree(file: File): String = {
    val data = if (file.isDirectory)
      s""","children":[${file.listFiles().sortBy(_.getName).map(serializeTree).mkString(",")}]"""
    else
      ""
    s"""{"name":"${file.getName}","path":"${file.getAbsolutePath}"$data}"""
  }

  private def parseMd(s: String) = {
    val parser = Parser.builder().build()
    val document = parser.parse(s)
    val renderer = HtmlRenderer.builder().build()
    renderer.render(document)
  }

  private def copyTree(sourceRoot: File, targetRoot: File) =
    listFilesRecursive(sourceRoot).sorted.foreach { source =>
      val path = source.getAbsolutePath.replace(sourceRoot.getAbsolutePath, targetRoot.getAbsolutePath)
      val file = new File(path)
      if (source.isDirectory)
        file.mkdirs()
      else
        Files.copy(source.toPath, file.toPath)
    }

  private def listFilesRecursive(f: File): Seq[File] =
    f +: (if (f.isDirectory) f.listFiles.flatMap(listFilesRecursive).toVector else Vector[File]())

}