From 96f184256f182c751b0568cc0b1999462bcb1abc Mon Sep 17 00:00:00 2001 From: Hariharan Ramanathan Date: Tue, 15 Jan 2019 11:51:57 +0100 Subject: [PATCH 1/7] Refactoring delphi cli sttp dependency for native image generation --- build.sbt | 21 +++- project/build.properties | 2 +- project/plugins.sbt | 2 +- .../de/upb/cs/swt/delphi/cli/Config.scala | 2 +- .../de/upb/cs/swt/delphi/cli/DelphiCLI.scala | 110 ++++++++---------- .../cs/swt/delphi/cli/commands/Command.scala | 41 ++++++- .../delphi/cli/commands/RetrieveCommand.scala | 2 +- .../delphi/cli/commands/SearchCommand.scala | 2 +- .../swt/delphi/cli/commands/TestCommand.scala | 8 +- .../de/upb/cs/swt/delphi/cli/package.scala | 30 +++++ 10 files changed, 143 insertions(+), 77 deletions(-) create mode 100644 src/main/scala/de/upb/cs/swt/delphi/cli/package.scala diff --git a/build.sbt b/build.sbt index 286164b..31739f4 100644 --- a/build.sbt +++ b/build.sbt @@ -29,6 +29,11 @@ libraryDependencies += "com.lihaoyi" %% "fansi" % "0.2.5" libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value libraryDependencies += "au.com.bytecode" % "opencsv" % "2.4" + +libraryDependencies += "com.softwaremill.sttp" %% "core" % "1.5.4" + + + debianPackageDependencies := Seq("java8-runtime-headless") lazy val cli = (project in file(".")). @@ -38,11 +43,23 @@ lazy val cli = (project in file(".")). enablePlugins(BuildInfoPlugin). enablePlugins(DebianPlugin). enablePlugins(WindowsPlugin). - + enablePlugins(GraalVMNativeImagePlugin). + settings( + graalVMNativeImageOptions++=Seq( + "--enable-https", + "--enable-http", + "--enable-all-security-services", + "--allow-incomplete-classpath", + "--enable-url-protocols=http,https" + ) + ). + enablePlugins(JDKPackagerPlugin). settings( buildInfoKeys := Seq[BuildInfoKey](name, version, scalaVersion, sbtVersion), - buildInfoPackage := "de.upb.cs.swt.delphi.cli" + buildInfoPackage := "de.upb.cs.swt.delphi.cli", ) scalastyleConfig := baseDirectory.value / "project" / "scalastyle-config.xml" trapExit := false +fork := true +connectInput := true diff --git a/project/build.properties b/project/build.properties index 210243d..7609b47 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version = 1.1.1 +sbt.version = 1.2.8 \ No newline at end of file diff --git a/project/plugins.sbt b/project/plugins.sbt index 705f861..86636a4 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,6 +1,6 @@ // build management and packaging addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0") -addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.2") +addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.15") // coverage addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1") diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/Config.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/Config.scala index cc5b016..fcdb9dc 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/Config.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/Config.scala @@ -23,7 +23,7 @@ package de.upb.cs.swt.delphi.cli * @param verbose Marker if logging should be verbose * @param mode The command to be run */ -case class Config(server: String = sys.env.getOrElse("DELPHI_SERVER", "https://delphi.cs.uni-paderborn.de/api/"), +case class Config(server: String = sys.env.getOrElse("DELPHI_SERVER", "https://delphi.cs.uni-paderborn.de/api"), verbose: Boolean = false, raw: Boolean = false, csv: String = "", diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala index 1c5be43..9555813 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala @@ -16,81 +16,71 @@ package de.upb.cs.swt.delphi.cli -import akka.actor.ActorSystem -import akka.http.scaladsl.Http -import de.upb.cs.swt.delphi.cli.commands.{RetrieveCommand, SearchCommand, TestCommand} - -import scala.concurrent.duration.Duration -import scala.concurrent.{Await, ExecutionContext} - +import de.upb.cs.swt.delphi.cli.commands.TestCommand /** * The application class for the Delphi command line interface */ -object DelphiCLI extends App { - - implicit val system = ActorSystem() +object DelphiCLI { - val cliParser = { - new scopt.OptionParser[Config]("delphi-cli") { - head("Delphi Command Line Tool", s"(${BuildInfo.version})") + private def cliParser = { + val parser = { + new scopt.OptionParser[Config]("delphi-cli") { + head("Delphi Command Line Tool", s"(${BuildInfo.version})") - version("version").text("Prints the version of the command line tool.") + version("version").text("Prints the version of the command line tool.") - help("help").text("Prints this help text.") - override def showUsageOnError = true + help("help").text("Prints this help text.") - opt[String]("server").action( (x,c) => c.copy(server = x)).text("The url to the Delphi server") - opt[Unit] (name = "raw").action((_,c) => c.copy(raw = true)).text("Output the raw results") - opt[Unit] (name = "silent").action((_,c) => c.copy(silent = true)).text("Suppress non-result output") + override def showUsageOnError = true - checkConfig(c => if (c.server.isEmpty()) failure("Option server is required.") else success) + opt[String]("server").action((x, c) => c.copy(server = x)).text("The url to the Delphi server") + opt[Unit](name = "raw").action((_, c) => c.copy(raw = true)).text("Output the raw results") + opt[Unit](name = "silent").action((_, c) => c.copy(silent = true)).text("Suppress non-result output") - cmd("test").action((_,c) => c.copy(mode = "test")) + checkConfig(c => if (c.server.isEmpty()) failure("Option server is required.") else success) - cmd("retrieve").action((s,c) => c.copy(mode = "retrieve")) - .text("Retrieve a project's description, specified by ID.") - .children( - arg[String]("id").action((x, c) => c.copy(id = x)).text("The ID of the project to retrieve"), - opt[String]("csv").action((x, c) => c.copy(csv = x)).text("Path to the output .csv file (overwrites existing file)"), - opt[Unit]('f', "file").action((_, c) => c.copy(opts = List("file"))).text("Use to load the ID from file, " + - "with the filepath given in place of the ID") - ) - - cmd("search").action((s, c) => c.copy(mode = "search")) - .text("Search artifact using a query.") - .children( - arg[String]("query").action((x,c) => c.copy(query = x)).text("The query to be used."), - opt[String]("csv").action((x, c) => c.copy(csv = x)).text("Path to the output .csv file (overwrites existing file)"), - opt[Int]("limit").action((x, c) => c.copy(limit = Some(x))).text("The maximal number of results returned."), - opt[Unit](name="list").action((_, c) => c.copy(list = true)).text("Output results as list (raw option overrides this)"), - opt[Int]("timeout").action((x, c) => c.copy(timeout = Some(x))).text("Timeout in seconds.") - ) - } - } + cmd("test").action((_, c) => c.copy(mode = "test")) + cmd("retrieve").action((s, c) => c.copy(mode = "retrieve")) + .text("Retrieve a project's description, specified by ID.") + .children( + arg[String]("id").action((x, c) => c.copy(id = x)).text("The ID of the project to retrieve"), + opt[String]("csv").action((x, c) => c.copy(csv = x)).text("Path to the output .csv file (overwrites existing file)"), + opt[Unit]('f', "file").action((_, c) => c.copy(opts = List("file"))).text("Use to load the ID from file, " + + "with the filepath given in place of the ID") + ) - cliParser.parse(args, Config()) match { - case Some(config) => - if (!config.silent) cliParser.showHeader() - config.mode match { - case "test" => TestCommand.execute(config) - case "retrieve" => RetrieveCommand.execute(config) - case "search" => SearchCommand.execute(config) - case x => config.consoleOutput.outputError(s"Unknown command: $x") + cmd("search").action((s, c) => c.copy(mode = "search")) + .text("Search artifact using a query.") + .children( + arg[String]("query").action((x, c) => c.copy(query = x)).text("The query to be used."), + opt[String]("csv").action((x, c) => c.copy(csv = x)).text("Path to the output .csv file (overwrites existing file)"), + opt[Int]("limit").action((x, c) => c.copy(limit = Some(x))).text("The maximal number of results returned."), + opt[Unit](name = "list").action((_, c) => c.copy(list = true)).text("Output results as list (raw option overrides this)"), + opt[Int]("timeout").action((x, c) => c.copy(timeout = Some(x))).text("Timeout in seconds.") + ) } - - case None => + } + parser } + def main(args: Array[String]): Unit = { + + System.setProperty("java.library.path", javaLibPath.get) + System.setProperty("javax.net.ssl.trustStore", trustStorePath.get) + System.setProperty("picocli.ansi", "true") + cliParser.parse(args, config) match { + case Some(config) => + if (!config.silent) cliParser.showHeader() + config.mode match { + case "test" => TestCommand.execute + // case "retrieve" => RetrieveCommand.execute(config) + // case "search" => SearchCommand.execute(config) + case x => config.consoleOutput.outputError(s"Unknown command: $x") + } + case None => + } - val poolShutdown = Http().shutdownAllConnectionPools() - Await.result(poolShutdown, Duration.Inf) - - implicit val ec: ExecutionContext = system.dispatcher - val terminationFuture = system.terminate() - - terminationFuture.onComplete { - sys.exit(0) } -} +} \ No newline at end of file diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/Command.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/Command.scala index 30b9e22..998ad47 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/Command.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/Command.scala @@ -22,11 +22,12 @@ import akka.http.scaladsl.model.Uri.Query import akka.http.scaladsl.model.{HttpRequest, HttpResponse, StatusCodes, Uri} import akka.stream.ActorMaterializer import akka.util.ByteString +import com.softwaremill.sttp._ import de.upb.cs.swt.delphi.cli.Config -import scala.concurrent.{Await, Future} import scala.concurrent.duration._ -import scala.util.{Failure, Success} +import scala.concurrent.{Await, Future} +import scala.util.Failure /** * Represents the implementation of a command of the CLI @@ -35,17 +36,19 @@ trait Command { /** * Executes the command implementation + * * @param config The current configuration for the command */ - def execute(config: Config)(implicit system : ActorSystem): Unit + def execute(implicit config: Config): Unit = {} /** * Implements a common request type using currying to avoid code duplication + * * @param target The endpoint to perform a Get request on * @param config The current configuration for the command */ - protected def executeGet(target: String, parameters: Map[String, String] = Map())(config: Config, system : ActorSystem) : Option[String] = { - implicit val sys : ActorSystem = system + protected def executeGet(target: String, parameters: Map[String, String] = Map())(config: Config, system: ActorSystem): Option[String] = { + implicit val sys: ActorSystem = system implicit val materializer = ActorMaterializer() implicit val executionContext = sys.dispatcher @@ -65,7 +68,7 @@ trait Command { entity.dataBytes.runFold(ByteString(""))(_ ++ _).map { body => Some(body.utf8String) } - case resp @ HttpResponse(code, _, _, _) => { + case resp@HttpResponse(code, _, _, _) => { error(config)("Artifact not found.") resp.discardEntityBytes() Future(None) @@ -75,9 +78,35 @@ trait Command { Await.result(resultString, Duration.Inf) } + /** + * Generic http GET request + * + * @param target Sub url in delphi server + * @param parameters Query params + * @return GET response + */ + protected def executeGet1(target: String, parameters: Map[String, String] = Map()) + (implicit config: Config, backend: SttpBackend[Id, Nothing]): Option[String] = { + + val request = sttp.get(uri"${config.server}/$target?$parameters") + config.consoleOutput.outputInformation(s"Sending request ${request.uri}") + val response = request.send() + response.body match { + case Left(value) => + error.apply(s"Request failed:\n $value") + None + case Right(value) => + Some(value) + } + } + + protected def information(implicit config: Config): String => Unit = config.consoleOutput.outputInformation _ + protected def reportResult(implicit config: Config): Any => Unit = config.consoleOutput.outputResult _ + protected def error(implicit config: Config): String => Unit = config.consoleOutput.outputError _ + protected def success(implicit config: Config): String => Unit = config.consoleOutput.outputSuccess _ protected def exportResult(implicit config: Config): Any => Unit = config.csvOutput.exportResult _ diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala index 817aa00..075182d 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala @@ -38,7 +38,7 @@ import scala.util.{Failure, Success} object RetrieveCommand extends Command with SprayJsonSupport with DefaultJsonProtocol { - override def execute(config: Config)(implicit system: ActorSystem): Unit = { + def execute(config: Config)(implicit system: ActorSystem): Unit = { implicit val ec = system.dispatcher implicit val materializer = ActorMaterializer() diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala index 24b6683..671db5e 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala @@ -44,7 +44,7 @@ object SearchCommand extends Command with SprayJsonSupport with DefaultJsonProto * * @param config The current configuration for the command */ - override def execute(config: Config)(implicit system: ActorSystem): Unit = { + def execute(config: Config)(implicit system: ActorSystem): Unit = { implicit val ec = system.dispatcher implicit val materializer = ActorMaterializer() diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/TestCommand.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/TestCommand.scala index 2589bea..ddd8b12 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/TestCommand.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/TestCommand.scala @@ -16,17 +16,17 @@ package de.upb.cs.swt.delphi.cli.commands -import akka.actor.ActorSystem import de.upb.cs.swt.delphi.cli.Config +import de.upb.cs.swt.delphi.cli._ /** * The implementation of the test command. * Tries to connect to the Delphi server and reports on the results of the version call. */ object TestCommand extends Command { - override def execute(config: Config)(implicit system : ActorSystem): Unit = executeGet( - "/version" - )(config, system).map(s => { + override def execute(implicit config: Config): Unit = executeGet1( + "version" + ).map(s => { success(config)("Successfully contacted Delphi server. ") information(config)("Server version: " + s) }) diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/package.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/package.scala new file mode 100644 index 0000000..95e9bde --- /dev/null +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/package.scala @@ -0,0 +1,30 @@ +// Copyright (C) 2018 The Delphi Team. +// See the LICENCE file distributed with this work for additional +// information regarding copyright ownership. +// +// 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 de.upb.cs.swt.delphi + +import com.softwaremill.sttp.HttpURLConnectionBackend + +package object cli { + implicit val config: Config = Config() + implicit val backend = HttpURLConnectionBackend() + + val javaLibPath = Option(System.getenv("JAVA_LIB_PATH")) + .orElse(Some("/usr/lib/jvm/default-java/lib/")) + + val trustStorePath = Option(System.getenv("JAVA_TRUSTSTORE")) + .orElse(Some("/usr/lib/jvm/default-java/lib/security/cacerts")) + +} From 3972bd46ddb968ee08b646ff4b1439ca90add9c0 Mon Sep 17 00:00:00 2001 From: Hariharan Ramanathan Date: Tue, 15 Jan 2019 15:29:27 +0100 Subject: [PATCH 2/7] Refactored retrieve command to sttp --- .../de/upb/cs/swt/delphi/cli/DelphiCLI.scala | 55 ++++++++----- .../cs/swt/delphi/cli/commands/Command.scala | 54 +------------ .../delphi/cli/commands/RetrieveCommand.scala | 79 ++++++++++--------- .../swt/delphi/cli/commands/TestCommand.scala | 15 ++-- .../de/upb/cs/swt/delphi/cli/package.scala | 30 ------- 5 files changed, 90 insertions(+), 143 deletions(-) delete mode 100644 src/main/scala/de/upb/cs/swt/delphi/cli/package.scala diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala index 9555813..55c30fe 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala @@ -16,13 +16,47 @@ package de.upb.cs.swt.delphi.cli -import de.upb.cs.swt.delphi.cli.commands.TestCommand +import com.softwaremill.sttp.{HttpURLConnectionBackend, Id, SttpBackend} +import de.upb.cs.swt.delphi.cli.commands._ /** * The application class for the Delphi command line interface */ object DelphiCLI { + + def main(args: Array[String]): Unit = { + + def getEnvOrElse(envVar: String, defaultPath: String) = sys.env.getOrElse(envVar, defaultPath) + + val javaLibPath = getEnvOrElse("JAVA_LIB_PATH", "/usr/lib/jvm/default-java/lib/") + + val trustStorePath = getEnvOrElse("JAVA_TRUSTSTORE", "/usr/lib/jvm/default-java/lib/security/cacerts") + + System.setProperty("java.library.path", javaLibPath) + System.setProperty("javax.net.ssl.trustStore", trustStorePath) + + cliParser.parse(args, Config()) match { + case Some(c) => + + implicit val config: Config = c + implicit val backend: SttpBackend[Id, Nothing] = HttpURLConnectionBackend() + + if (!config.silent) cliParser.showHeader() + + config.mode match { + case "test" => TestCommand.execute + case "retrieve" => RetrieveCommand.execute + // case "search" => SearchCommand.execute(config) + case x => config.consoleOutput.outputError(s"Unknown command: $x") + } + + + case None => + } + + } + private def cliParser = { val parser = { new scopt.OptionParser[Config]("delphi-cli") { @@ -64,23 +98,4 @@ object DelphiCLI { } parser } - - def main(args: Array[String]): Unit = { - - System.setProperty("java.library.path", javaLibPath.get) - System.setProperty("javax.net.ssl.trustStore", trustStorePath.get) - System.setProperty("picocli.ansi", "true") - cliParser.parse(args, config) match { - case Some(config) => - if (!config.silent) cliParser.showHeader() - config.mode match { - case "test" => TestCommand.execute - // case "retrieve" => RetrieveCommand.execute(config) - // case "search" => SearchCommand.execute(config) - case x => config.consoleOutput.outputError(s"Unknown command: $x") - } - case None => - } - - } } \ No newline at end of file diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/Command.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/Command.scala index 998ad47..307c76a 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/Command.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/Command.scala @@ -16,19 +16,9 @@ package de.upb.cs.swt.delphi.cli.commands -import akka.actor.ActorSystem -import akka.http.scaladsl.Http -import akka.http.scaladsl.model.Uri.Query -import akka.http.scaladsl.model.{HttpRequest, HttpResponse, StatusCodes, Uri} -import akka.stream.ActorMaterializer -import akka.util.ByteString import com.softwaremill.sttp._ import de.upb.cs.swt.delphi.cli.Config -import scala.concurrent.duration._ -import scala.concurrent.{Await, Future} -import scala.util.Failure - /** * Represents the implementation of a command of the CLI */ @@ -39,54 +29,18 @@ trait Command { * * @param config The current configuration for the command */ - def execute(implicit config: Config): Unit = {} - - /** - * Implements a common request type using currying to avoid code duplication - * - * @param target The endpoint to perform a Get request on - * @param config The current configuration for the command - */ - protected def executeGet(target: String, parameters: Map[String, String] = Map())(config: Config, system: ActorSystem): Option[String] = { - implicit val sys: ActorSystem = system - implicit val materializer = ActorMaterializer() - implicit val executionContext = sys.dispatcher - - val uri = Uri(config.server) - config.consoleOutput.outputInformation(s"Contacting server ${uri}...") + def execute(implicit config: Config, backend: SttpBackend[Id, Nothing]): Unit = {} - val responseFuture = Http().singleRequest(HttpRequest(uri = uri.withPath(uri.path + target).withQuery(Query(parameters)))) - - responseFuture.onComplete { - case Failure(_) => error(config)(s"Could not reach server ${config.server}.") - case _ => - } - - val result = Await.result(responseFuture, 30 seconds) - val resultString = result match { - case HttpResponse(StatusCodes.OK, headers, entity, _) => - entity.dataBytes.runFold(ByteString(""))(_ ++ _).map { body => - Some(body.utf8String) - } - case resp@HttpResponse(code, _, _, _) => { - error(config)("Artifact not found.") - resp.discardEntityBytes() - Future(None) - } - } - - Await.result(resultString, Duration.Inf) - } /** * Generic http GET request * - * @param target Sub url in delphi server + * @param target Sub url in delphi server * @param parameters Query params * @return GET response */ - protected def executeGet1(target: String, parameters: Map[String, String] = Map()) - (implicit config: Config, backend: SttpBackend[Id, Nothing]): Option[String] = { + protected def executeGet(target: String, parameters: Map[String, String] = Map()) + (implicit config: Config, backend: SttpBackend[Id, Nothing]): Option[String] = { val request = sttp.get(uri"${config.server}/$target?$parameters") config.consoleOutput.outputInformation(s"Sending request ${request.uri}") diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala index 075182d..797c8c7 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala @@ -16,31 +16,21 @@ package de.upb.cs.swt.delphi.cli.commands -import akka.actor.ActorSystem -import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport -import akka.http.scaladsl.unmarshalling.Unmarshal -import akka.stream.ActorMaterializer -import de.upb.cs.swt.delphi.cli.Config +import com.softwaremill.sttp.{Id, SttpBackend} +import de.upb.cs.swt.delphi.cli._ import de.upb.cs.swt.delphi.cli.artifacts.RetrieveResult -import de.upb.cs.swt.delphi.cli.artifacts.SearchResultJson._ -import de.upb.cs.swt.delphi.cli.commands.SearchCommand.information -import spray.json.DefaultJsonProtocol +import spray.json._ -import scala.concurrent.Await -import scala.concurrent.duration.Duration import scala.io.Source -import scala.util.{Failure, Success} /** * The implementation of the retrieve command. * Retrieves the contents of the file at the endpoint specified by the config file, and prints them to stdout */ -object RetrieveCommand extends Command with SprayJsonSupport with DefaultJsonProtocol { +object RetrieveCommand extends Command with DefaultJsonProtocol { - def execute(config: Config)(implicit system: ActorSystem): Unit = { - implicit val ec = system.dispatcher - implicit val materializer = ActorMaterializer() + override def execute(implicit config: Config, backend: SttpBackend[Id, Nothing]): Unit = { //Checks whether the ID should be loaded from a file or not, and either returns the first line // of the given file if it is, or the specified ID otherwise @@ -56,37 +46,54 @@ object RetrieveCommand extends Command with SprayJsonSupport with DefaultJsonPro } val result = executeGet( - s"/retrieve/$checkTarget", + s"retrieve/$checkTarget", Map("pretty" -> "") - )(config, system) + ) - result.map(s => { + result.foreach(s => { if (config.raw) { - reportResult(config)(s) + reportResult.apply(s) } - if (!config.raw || !config.csv.equals("")) { - val unmarshalledFuture = Unmarshal(s).to[List[RetrieveResult]] + import artifacts.SearchResultJson._ - unmarshalledFuture.transform { - case Success(unmarshalled) => { - val unmarshalled = Await.result(unmarshalledFuture, Duration.Inf) - success(config)(s"Found ${unmarshalled.size} item(s).") - reportResult(config)(unmarshalled) + //TODO: convertTo[List[RetrieveResult]] not working ??? - if(!config.csv.equals("")) { - exportResult(config)(unmarshalled) - information(config)("Results written to file '" + config.csv + "'") - } + val jsonArr = s.parseJson.asInstanceOf[JsArray].elements + val retrieveResults = jsonArr.map(r => r.convertTo[RetrieveResult]) - Success(unmarshalled) - } - case Failure(e) => { - error(config)(s) - Failure(e) - } + success.apply(s"Found ${retrieveResults.size} item(s).") + reportResult.apply(retrieveResults) + if (!config.csv.equals("")) { + exportResult.apply(retrieveResults) + information.apply("Results written to file '" + config.csv + "'") } } + + }) } } + +/* if (!config.raw || !config.csv.equals("")) { + val unmarshalledFuture = Unmarshal(s).to[List[RetrieveResult]] + + unmarshalledFuture.transform { + case Success(unmarshalled) => { + val unmarshalled = Await.result(unmarshalledFuture, Duration.Inf) + success.apply(s"Found ${unmarshalled.size} item(s).") + reportResult.apply(unmarshalled) + + if (!config.csv.equals("")) { + exportResult.apply(unmarshalled) + information.apply("Results written to file '" + config.csv + "'") + } + + Success(unmarshalled) + } + case Failure(e) => { + error.apply(s) + Failure(e) + } + } + }*/ \ No newline at end of file diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/TestCommand.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/TestCommand.scala index ddd8b12..4101281 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/TestCommand.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/TestCommand.scala @@ -16,18 +16,19 @@ package de.upb.cs.swt.delphi.cli.commands +import com.softwaremill.sttp.{Id, SttpBackend} import de.upb.cs.swt.delphi.cli.Config -import de.upb.cs.swt.delphi.cli._ /** * The implementation of the test command. * Tries to connect to the Delphi server and reports on the results of the version call. */ object TestCommand extends Command { - override def execute(implicit config: Config): Unit = executeGet1( - "version" - ).map(s => { - success(config)("Successfully contacted Delphi server. ") - information(config)("Server version: " + s) - }) + override def execute(implicit config: Config,backend: SttpBackend[Id, Nothing]): Unit = { + executeGet("version") + .foreach(s => { + success.apply("Successfully contacted Delphi server. ") + information.apply("Server version: " + s) + }) + } } diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/package.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/package.scala deleted file mode 100644 index 95e9bde..0000000 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/package.scala +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2018 The Delphi Team. -// See the LICENCE file distributed with this work for additional -// information regarding copyright ownership. -// -// 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 de.upb.cs.swt.delphi - -import com.softwaremill.sttp.HttpURLConnectionBackend - -package object cli { - implicit val config: Config = Config() - implicit val backend = HttpURLConnectionBackend() - - val javaLibPath = Option(System.getenv("JAVA_LIB_PATH")) - .orElse(Some("/usr/lib/jvm/default-java/lib/")) - - val trustStorePath = Option(System.getenv("JAVA_TRUSTSTORE")) - .orElse(Some("/usr/lib/jvm/default-java/lib/security/cacerts")) - -} From 1de2c18e7d1e774b1334549c23e2567aee91ed29 Mon Sep 17 00:00:00 2001 From: Hariharan Ramanathan Date: Wed, 23 Jan 2019 22:35:50 +0100 Subject: [PATCH 3/7] Fixing encoded url issue for retrieve command --- build.sbt | 12 ++++--- .../de/upb/cs/swt/delphi/cli/DelphiCLI.scala | 4 ++- .../cs/swt/delphi/cli/commands/Command.scala | 10 +++--- .../delphi/cli/commands/RetrieveCommand.scala | 31 +++---------------- .../swt/delphi/cli/commands/TestCommand.scala | 4 +-- 5 files changed, 22 insertions(+), 39 deletions(-) diff --git a/build.sbt b/build.sbt index 31739f4..210d9a6 100644 --- a/build.sbt +++ b/build.sbt @@ -1,6 +1,6 @@ scalaVersion := "2.12.4" -name := "delphi" +name := "delphi-cli" version := "1.0.0-SNAPSHOT" maintainer := "Ben Hermann " @@ -28,10 +28,12 @@ libraryDependencies += "de.vandermeer" % "asciitable" % "0.3.2" libraryDependencies += "com.lihaoyi" %% "fansi" % "0.2.5" libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value libraryDependencies += "au.com.bytecode" % "opencsv" % "2.4" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "test" - -libraryDependencies += "com.softwaremill.sttp" %% "core" % "1.5.4" - +libraryDependencies ++= Seq( + "com.softwaremill.sttp" %% "core" % "1.5.4", + "com.softwaremill.sttp" %% "spray-json" % "1.5.4" +) debianPackageDependencies := Seq("java8-runtime-headless") @@ -45,7 +47,7 @@ lazy val cli = (project in file(".")). enablePlugins(WindowsPlugin). enablePlugins(GraalVMNativeImagePlugin). settings( - graalVMNativeImageOptions++=Seq( + graalVMNativeImageOptions ++= Seq( "--enable-https", "--enable-http", "--enable-all-security-services", diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala index 55c30fe..cd6185d 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala @@ -16,7 +16,6 @@ package de.upb.cs.swt.delphi.cli -import com.softwaremill.sttp.{HttpURLConnectionBackend, Id, SttpBackend} import de.upb.cs.swt.delphi.cli.commands._ /** @@ -39,6 +38,9 @@ object DelphiCLI { cliParser.parse(args, Config()) match { case Some(c) => + import com.softwaremill.sttp._ + import scala.concurrent.duration._ + implicit val config: Config = c implicit val backend: SttpBackend[Id, Nothing] = HttpURLConnectionBackend() diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/Command.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/Command.scala index 307c76a..d3bc8bf 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/Command.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/Command.scala @@ -33,16 +33,18 @@ trait Command { /** - * Generic http GET request + * Http GET request template * * @param target Sub url in delphi server * @param parameters Query params * @return GET response */ - protected def executeGet(target: String, parameters: Map[String, String] = Map()) + protected def executeGet(paths: Seq[String], parameters: Map[String, String] = Map()) (implicit config: Config, backend: SttpBackend[Id, Nothing]): Option[String] = { - - val request = sttp.get(uri"${config.server}/$target?$parameters") + val serverUrl = uri"${config.server}" + val oldPath = serverUrl.path + val reqUrl = serverUrl.path(oldPath ++ paths).params(parameters) + val request = sttp.get(reqUrl) config.consoleOutput.outputInformation(s"Sending request ${request.uri}") val response = request.send() response.body match { diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala index 797c8c7..6bf7f23 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala @@ -45,8 +45,9 @@ object RetrieveCommand extends Command with DefaultJsonProtocol { } } + println(config.id) val result = executeGet( - s"retrieve/$checkTarget", + Seq("retrieve", checkTarget), Map("pretty" -> "") ) @@ -57,7 +58,8 @@ object RetrieveCommand extends Command with DefaultJsonProtocol { if (!config.raw || !config.csv.equals("")) { import artifacts.SearchResultJson._ - //TODO: convertTo[List[RetrieveResult]] not working ??? + //TODO: Direct convertTo[List[RetrieveResult]] not working ??? + val jsonArr = s.parseJson.asInstanceOf[JsArray].elements val retrieveResults = jsonArr.map(r => r.convertTo[RetrieveResult]) @@ -69,31 +71,6 @@ object RetrieveCommand extends Command with DefaultJsonProtocol { information.apply("Results written to file '" + config.csv + "'") } } - - }) } } - -/* if (!config.raw || !config.csv.equals("")) { - val unmarshalledFuture = Unmarshal(s).to[List[RetrieveResult]] - - unmarshalledFuture.transform { - case Success(unmarshalled) => { - val unmarshalled = Await.result(unmarshalledFuture, Duration.Inf) - success.apply(s"Found ${unmarshalled.size} item(s).") - reportResult.apply(unmarshalled) - - if (!config.csv.equals("")) { - exportResult.apply(unmarshalled) - information.apply("Results written to file '" + config.csv + "'") - } - - Success(unmarshalled) - } - case Failure(e) => { - error.apply(s) - Failure(e) - } - } - }*/ \ No newline at end of file diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/TestCommand.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/TestCommand.scala index 4101281..2f11b3e 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/TestCommand.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/TestCommand.scala @@ -24,8 +24,8 @@ import de.upb.cs.swt.delphi.cli.Config * Tries to connect to the Delphi server and reports on the results of the version call. */ object TestCommand extends Command { - override def execute(implicit config: Config,backend: SttpBackend[Id, Nothing]): Unit = { - executeGet("version") + override def execute(implicit config: Config, backend: SttpBackend[Id, Nothing]): Unit = { + executeGet(Seq("version")) .foreach(s => { success.apply("Successfully contacted Delphi server. ") information.apply("Server version: " + s) From b252d4e608051ecc363a5e66c6f76f970c0990fd Mon Sep 17 00:00:00 2001 From: Hariharan Ramanathan Date: Thu, 24 Jan 2019 11:47:53 +0100 Subject: [PATCH 4/7] Refactoring search command to sttp --- .../de/upb/cs/swt/delphi/cli/DelphiCLI.scala | 2 +- .../delphi/cli/commands/RetrieveCommand.scala | 3 +- .../delphi/cli/commands/SearchCommand.scala | 152 ++++++++---------- .../cs/swt/delphi/cli/commands/package.scala | 28 ++++ 4 files changed, 95 insertions(+), 90 deletions(-) create mode 100644 src/main/scala/de/upb/cs/swt/delphi/cli/commands/package.scala diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala index cd6185d..d0d9b88 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala @@ -49,7 +49,7 @@ object DelphiCLI { config.mode match { case "test" => TestCommand.execute case "retrieve" => RetrieveCommand.execute - // case "search" => SearchCommand.execute(config) + case "search" => SearchCommand.execute case x => config.consoleOutput.outputError(s"Unknown command: $x") } diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala index 6bf7f23..d290cd6 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala @@ -27,7 +27,7 @@ import scala.io.Source * The implementation of the retrieve command. * Retrieves the contents of the file at the endpoint specified by the config file, and prints them to stdout */ -object RetrieveCommand extends Command with DefaultJsonProtocol { +object RetrieveCommand extends Command { override def execute(implicit config: Config, backend: SttpBackend[Id, Nothing]): Unit = { @@ -45,7 +45,6 @@ object RetrieveCommand extends Command with DefaultJsonProtocol { } } - println(config.id) val result = executeGet( Seq("retrieve", checkTarget), Map("pretty" -> "") diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala index 671db5e..634f308 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala @@ -16,124 +16,102 @@ package de.upb.cs.swt.delphi.cli.commands -import java.util.concurrent.{TimeUnit, TimeoutException} - -import akka.actor.ActorSystem -import akka.http.scaladsl.Http -import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport -import akka.http.scaladsl.marshalling.Marshal -import akka.http.scaladsl.model._ -import akka.http.scaladsl.unmarshalling.Unmarshal -import akka.stream.ActorMaterializer -import akka.util.ByteString -import de.upb.cs.swt.delphi.cli.Config +import java.util.concurrent.TimeUnit + +import com.softwaremill.sttp._ +import com.softwaremill.sttp.sprayJson._ import de.upb.cs.swt.delphi.cli.artifacts.SearchResult -import de.upb.cs.swt.delphi.cli.artifacts.SearchResultJson._ -import spray.json.DefaultJsonProtocol +import de.upb.cs.swt.delphi.cli.{Config, artifacts} +import spray.json._ import scala.concurrent.duration._ -import scala.concurrent.{Await, ExecutionContextExecutor, Future} -import scala.util.{Failure, Success, Try} -object SearchCommand extends Command with SprayJsonSupport with DefaultJsonProtocol { +object SearchCommand extends Command with DefaultJsonProtocol{ - val searchTimeout: Int = 10 + val searchTimeout = 10.seconds + val TIMEOUT_CODE = 408 /** * Executes the command implementation * * @param config The current configuration for the command */ - def execute(config: Config)(implicit system: ActorSystem): Unit = { - implicit val ec = system.dispatcher - implicit val materializer = ActorMaterializer() + override def execute(implicit config: Config, backend: SttpBackend[Id, Nothing]): Unit = { def query = config.query - information(config)(s"Searching for artifacts matching ${'"'}$query${'"'}.") - val start = System.nanoTime() + information.apply(s"Searching for artifacts matching ${'"'}$query${'"'}.") - implicit val queryFormat = jsonFormat2(Query) - val baseUri = Uri(config.server) - val prettyParam = Map("pretty" -> "") - val searchUri = baseUri.withPath(baseUri.path + "/search").withQuery(akka.http.scaladsl.model.Uri.Query(prettyParam)) - val responseFuture = Marshal(Query(query, config.limit)).to[RequestEntity] flatMap { entity => - Http().singleRequest(HttpRequest(uri = searchUri, method = HttpMethods.POST, entity = entity)) - } - Try(Await.result(responseFuture, Duration(config.timeout.getOrElse(searchTimeout) + " seconds"))). - map(response => parseResponse(response, config, start)(ec, materializer)). - recover { - case e : TimeoutException => { - error(config)("The query timed out after " + (System.nanoTime() - start).nanos.toUnit(TimeUnit.SECONDS) + - " seconds. To set a longer timeout, use the --timeout option.") - Failure(e) - } - } + val queryParams = Map("pretty" -> "") + val queryPayload: Query = Query(query,config.limit) + val searchUri = uri"${config.server}/search?$queryParams" + + val request = sttp.body(queryPayload.toJson).post(searchUri) + + val (res, time) = processRequest(request) + res.foreach(processResults(_, time)) } - private def parseResponse(response: HttpResponse, config: Config, start: Long) - (implicit ec: ExecutionContextExecutor, materializer: ActorMaterializer): Unit = { + private def processRequest(req: Request[String, Nothing]) + (implicit config: Config, + backend: SttpBackend[Id, Nothing]): (Option[String], FiniteDuration) = { + val start = System.nanoTime() + val res: Id[Response[String]] = req.readTimeout(searchTimeout).send() + val end = System.nanoTime() + val took = (end - start).nanos - val resultFuture: Future[String] = response match { - case HttpResponse(StatusCodes.OK, headers, entity, _) => - entity.dataBytes.runFold(ByteString(""))(_ ++ _).map { body => - body.utf8String - } - case resp@HttpResponse(code, _, _, _) => { - error(config)("Request failed, response code: " + code) - resp.discardEntityBytes() - Future("") - } - } + if (res.code == TIMEOUT_CODE) { - val result = Await.result(resultFuture, Duration.Inf) + error.apply(s"The query timed out after ${took.toSeconds} seconds. " + + "To set a longer timeout, use the --timeout option.") + } + val resStr = res.body match { + case Left(v) => + error.apply(s"Search request failed \n $v") + println(v) + None + case Right(v) => + Some(v) + } + (resStr, took) + } - val took = (System.nanoTime() - start).nanos.toUnit(TimeUnit.SECONDS) + private def processResults(res: String, queryRuntime: FiniteDuration)(implicit config: Config) = { - if (config.raw || result.equals("")) { - reportResult(config)(result) + if (config.raw || res.equals("")) { + reportResult.apply(res) + } + if (!(config.raw || res.equals("")) || !config.csv.equals("")) { + import artifacts.SearchResultJson._ + val jsonArr = res.parseJson.asInstanceOf[JsArray].elements + val retrieveResults = jsonArr.map(r => r.convertTo[SearchResult]).toList + onProperSearchResults(retrieveResults) } - if(!(config.raw || result.equals("")) || !config.csv.equals("")) { - val unmarshalledFuture = Unmarshal(result).to[List[SearchResult]] + def onProperSearchResults(sr: List[SearchResult]) = { - val processFuture = unmarshalledFuture.transform { - case Success(unmarshalled) => { - processResults(config, unmarshalled, took) - Success(unmarshalled) - } - case Failure(e) => { - error(config)(result) - Failure(e) + val capMessage = { + config.limit match { + case Some(limit) if (limit <= sr.size) + => s"Results may be capped by result limit set to $limit." + case None if (sr.size >= 50) + => "Results may be capped by default limit of 50 returned results. Use --limit to extend the result set." + case _ + => "" } } - } - } - private def processResults(config: Config, results: List[SearchResult], queryRuntime: Double) = { - val capMessage = { - config.limit match { - case Some(limit) if (limit <= results.size) - => s"Results may be capped by result limit set to $limit." - case None if (results.size >= 50) - => "Results may be capped by default limit of 50 returned results. Use --limit to extend the result set." - case _ - => "" - } - } - success(config)(s"Found ${results.size} item(s). $capMessage") - reportResult(config)(results) + success.apply(s"Found ${sr.size} item(s). $capMessage") + reportResult.apply(sr) - information(config)(f"Query took $queryRuntime%.2fs.") + information.apply(f"Query took ${queryRuntime.toUnit(TimeUnit.SECONDS)}%.2fs.") - if(!config.csv.equals("")) { - exportResult(config)(results) - information(config)("Results written to file '" + config.csv + "'") + if (!config.csv.equals("")) { + exportResult.apply(sr) + information.apply("Results written to file '" + config.csv + "'") + } } } - case class Query(query: String, - limit: Option[Int] = None) - } diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/package.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/package.scala new file mode 100644 index 0000000..8975631 --- /dev/null +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/package.scala @@ -0,0 +1,28 @@ +// Copyright (C) 2018 The Delphi Team. +// See the LICENCE file distributed with this work for additional +// information regarding copyright ownership. +// +// 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 de.upb.cs.swt.delphi.cli + +import spray.json._ + +package object commands extends DefaultJsonProtocol { + + + case class Query(query: String, + limit: Option[Int] = None) + + implicit val queryFormat = jsonFormat2(Query) + +} From 07242692c337d6ce5757f205db8ae52b1b488b8e Mon Sep 17 00:00:00 2001 From: Hariharan Ramanathan Date: Fri, 25 Jan 2019 16:58:31 +0100 Subject: [PATCH 5/7] Implementing codacy suggestions --- .../scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala | 3 +-- .../cs/swt/delphi/cli/commands/RetrieveCommand.scala | 2 +- .../cs/swt/delphi/cli/commands/SearchCommand.scala | 11 +++++------ 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala index d0d9b88..6148ef6 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/DelphiCLI.scala @@ -16,6 +16,7 @@ package de.upb.cs.swt.delphi.cli +import com.softwaremill.sttp._ import de.upb.cs.swt.delphi.cli.commands._ /** @@ -38,8 +39,6 @@ object DelphiCLI { cliParser.parse(args, Config()) match { case Some(c) => - import com.softwaremill.sttp._ - import scala.concurrent.duration._ implicit val config: Config = c implicit val backend: SttpBackend[Id, Nothing] = HttpURLConnectionBackend() diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala index d290cd6..93a64df 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/RetrieveCommand.scala @@ -19,6 +19,7 @@ package de.upb.cs.swt.delphi.cli.commands import com.softwaremill.sttp.{Id, SttpBackend} import de.upb.cs.swt.delphi.cli._ import de.upb.cs.swt.delphi.cli.artifacts.RetrieveResult +import de.upb.cs.swt.delphi.cli.artifacts.SearchResultJson._ import spray.json._ import scala.io.Source @@ -55,7 +56,6 @@ object RetrieveCommand extends Command { reportResult.apply(s) } if (!config.raw || !config.csv.equals("")) { - import artifacts.SearchResultJson._ //TODO: Direct convertTo[List[RetrieveResult]] not working ??? diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala index 634f308..e7bad31 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala @@ -1,4 +1,4 @@ -// Copyright (C) 2018 The Delphi Team. + // Copyright (C) 2018 The Delphi Team. // See the LICENCE file distributed with this work for additional // information regarding copyright ownership. // @@ -20,8 +20,9 @@ import java.util.concurrent.TimeUnit import com.softwaremill.sttp._ import com.softwaremill.sttp.sprayJson._ +import de.upb.cs.swt.delphi.cli.Config import de.upb.cs.swt.delphi.cli.artifacts.SearchResult -import de.upb.cs.swt.delphi.cli.{Config, artifacts} +import de.upb.cs.swt.delphi.cli.artifacts.SearchResultJson._ import spray.json._ import scala.concurrent.duration._ @@ -29,7 +30,7 @@ import scala.concurrent.duration._ object SearchCommand extends Command with DefaultJsonProtocol{ val searchTimeout = 10.seconds - val TIMEOUT_CODE = 408 + val timeoutCode = 408 /** * Executes the command implementation @@ -61,7 +62,7 @@ object SearchCommand extends Command with DefaultJsonProtocol{ val end = System.nanoTime() val took = (end - start).nanos - if (res.code == TIMEOUT_CODE) { + if (res.code == timeoutCode) { error.apply(s"The query timed out after ${took.toSeconds} seconds. " + "To set a longer timeout, use the --timeout option.") @@ -69,7 +70,6 @@ object SearchCommand extends Command with DefaultJsonProtocol{ val resStr = res.body match { case Left(v) => error.apply(s"Search request failed \n $v") - println(v) None case Right(v) => Some(v) @@ -83,7 +83,6 @@ object SearchCommand extends Command with DefaultJsonProtocol{ reportResult.apply(res) } if (!(config.raw || res.equals("")) || !config.csv.equals("")) { - import artifacts.SearchResultJson._ val jsonArr = res.parseJson.asInstanceOf[JsArray].elements val retrieveResults = jsonArr.map(r => r.convertTo[SearchResult]).toList onProperSearchResults(retrieveResults) From cc3306087a31d83610f7e0a9a8237a49f847a9fa Mon Sep 17 00:00:00 2001 From: Hariharan Ramanathan Date: Thu, 7 Mar 2019 19:00:15 +0100 Subject: [PATCH 6/7] Fixing codacy issue --- .../scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala index e7bad31..edb5c66 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/cli/commands/SearchCommand.scala @@ -1,4 +1,4 @@ - // Copyright (C) 2018 The Delphi Team. +// Copyright (C) 2018 The Delphi Team. // See the LICENCE file distributed with this work for additional // information regarding copyright ownership. // From 7d8068a5b1c3bf7869e8c647bbe18f2597d4c1c1 Mon Sep 17 00:00:00 2001 From: Hariharan Ramanathan Date: Thu, 7 Mar 2019 20:38:21 +0100 Subject: [PATCH 7/7] Renaming the project to delphi --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 210d9a6..e7b264f 100644 --- a/build.sbt +++ b/build.sbt @@ -1,6 +1,6 @@ scalaVersion := "2.12.4" -name := "delphi-cli" +name := "delphi" version := "1.0.0-SNAPSHOT" maintainer := "Ben Hermann "