diff --git a/build.sbt b/build.sbt
new file mode 100644
index 0000000..0e1ccc0
--- /dev/null
+++ b/build.sbt
@@ -0,0 +1,96 @@
+import scala.xml.Group
+
+val manifestSetting = packageOptions += {
+ Package.ManifestAttributes(
+ "Created-By" -> "Simple Build Tool",
+ "Built-By" -> System.getProperty("user.name"),
+ "Build-Jdk" -> System.getProperty("java.version"),
+ "Specification-Title" -> name.value,
+ "Specification-Version" -> version.value,
+ "Specification-Vendor" -> organization.value,
+ "Implementation-Title" -> name.value,
+ "Implementation-Version" -> version.value,
+ "Implementation-Vendor-Id" -> organization.value,
+ "Implementation-Vendor" -> organization.value
+ )
+}
+
+val publishSettings: Seq[Setting[_]] = Seq(
+ publishTo := {
+ val res =
+ if (version.value.trim.endsWith("SNAPSHOT"))
+ Opts.resolver.sonatypeSnapshots
+ else
+ Opts.resolver.sonatypeStaging
+ Some(res)
+ },
+ publishMavenStyle := true,
+ publishArtifact in Test := false,
+ pomIncludeRepository := { x => false }
+)
+
+val mavenCentralFrouFrou = Seq(
+ homepage := Some(new URL("http://swagger.io")),
+ startYear := Some(2009),
+ licenses := Seq(("ASL", new URL("http://github.com/swagger-api/swagger-async-httpclient/raw/HEAD/LICENSE"))),
+ pomExtra := pomExtra.value ++ Group(
+
+ http://github.com/swagger-api/swagger-async-httpclient
+ scm:git:git://github.com/swagger-api/swagger-async-httpclient.git
+
+
+
+ casualjim
+ Ivan Porto Carrero
+ http://flanders.co.nz/
+
+
+ )
+)
+
+val projectSettings = Seq(
+ organization := "io.swagger",
+ name := "swagger-async-httpclient",
+ scalaVersion := "2.11.12",
+ scalacOptions ++= Seq("-unchecked", "-deprecation", "-optimize", "-Xcheckinit", "-encoding", "utf8"),
+ javacOptions in compile ++= Seq("-Xlint:deprecation"),
+ manifestSetting,
+ autoCompilerPlugins := true,
+ parallelExecution in Test := false,
+ commands += Command.args("s", "") { (state, args) =>
+ args.mkString(" ") ! state.log
+ state
+ },
+ TaskKey[Unit]("gc", "runs garbage collector") := {
+ streams.value.log.info("requesting garbage collection")
+ System.gc()
+ }
+)
+
+val buildInfoConfig: Seq[Setting[_]] = Seq(
+ buildInfoKeys := Seq[BuildInfoKey](name, version, scalaVersion, sbtVersion),
+ buildInfoPackage := organization(_ + ".client.async").value
+)
+
+val defaultSettings =
+ Defaults.coreDefaultSettings ++ buildInfoConfig ++ projectSettings ++ publishSettings ++ mavenCentralFrouFrou
+
+
+lazy val root = Project(
+ id = "swagger-async-httpclient",
+ base = file("."),
+ settings = defaultSettings ++ Seq(
+ libraryDependencies ++= Seq(
+ "org.scalatra.rl" %% "rl" % "0.4.10",
+ "org.slf4j" % "slf4j-api" % "1.7.25",
+ "ch.qos.logback" % "logback-classic" % "1.2.3" % "provided",
+ "org.json4s" %% "json4s-jackson" % "3.5.3",
+ "com.googlecode.juniversalchardet" % "juniversalchardet" % "1.0.3",
+ "eu.medsea.mimeutil" % "mime-util" % "2.1.3" exclude("org.slf4j", "slf4j-log4j12") exclude("log4j", "log4j"),
+ "com.ning" % "async-http-client" % "1.8.17",
+ "com.typesafe.scala-logging" %% "scala-logging" % "3.7.2"
+ )
+ )
+)
+
+enablePlugins(BuildInfoPlugin)
diff --git a/project/build.properties b/project/build.properties
index 5075289..8b697bb 100644
--- a/project/build.properties
+++ b/project/build.properties
@@ -1 +1 @@
-sbt.version=0.13.5
\ No newline at end of file
+sbt.version=1.1.0
diff --git a/project/build.scala b/project/build.scala
deleted file mode 100644
index 51bca07..0000000
--- a/project/build.scala
+++ /dev/null
@@ -1,136 +0,0 @@
-import sbt._
-import Keys._
-import sbtrelease.ReleasePlugin._
-import sbtbuildinfo.Plugin._
-import scala.xml.Group
-
-object build extends Build {
-
- val manifestSetting = packageOptions <+= (name, version, organization) map {
- (title, version, vendor) =>
- Package.ManifestAttributes(
- "Created-By" -> "Simple Build Tool",
- "Built-By" -> System.getProperty("user.name"),
- "Build-Jdk" -> System.getProperty("java.version"),
- "Specification-Title" -> title,
- "Specification-Version" -> version,
- "Specification-Vendor" -> vendor,
- "Implementation-Title" -> title,
- "Implementation-Version" -> version,
- "Implementation-Vendor-Id" -> vendor,
- "Implementation-Vendor" -> vendor)
- }
-
- val publishSettings: Seq[Setting[_]] = Seq(
- publishTo <<= (version) { version: String =>
- val res =
- if (version.trim.endsWith("SNAPSHOT"))
- Opts.resolver.sonatypeSnapshots
- else
- Opts.resolver.sonatypeStaging
- Some(res)
- },
- publishMavenStyle := true,
- publishArtifact in Test := false,
- pomIncludeRepository := { x => false }
- )
-
- val mavenCentralFrouFrou = Seq(
- homepage := Some(new URL("http://swagger.io")),
- startYear := Some(2009),
- licenses := Seq(("ASL", new URL("http://github.com/swagger-api/swagger-async-httpclient/raw/HEAD/LICENSE"))),
- pomExtra <<= (pomExtra, name, description) {(pom, name, desc) => pom ++ Group(
-
- http://github.com/swagger-api/swagger-async-httpclient
- scm:git:git://github.com/swagger-api/swagger-async-httpclient.git
-
-
-
- casualjim
- Ivan Porto Carrero
- http://flanders.co.nz/
-
-
- )}
- )
-
- def versionSpecificSourcesIn(c: Configuration) =
- unmanagedSourceDirectories in c <+= (scalaVersion, sourceDirectory in c) {
- case (v, dir) if v startsWith "2.9" => dir / "scala_2.9"
- case (v, dir) if v startsWith "2.10" => dir / "scala_2.10"
- case (v, dir) if v startsWith "2.11" => dir / "scala_2.11"
- }
-
- val projectSettings = Seq(
- organization := "io.swagger",
- name := "swagger-async-httpclient",
- scalaVersion := "2.11.7",
- crossScalaVersions := Seq("2.10.4", "2.11.7"),
- scalacOptions ++= Seq("-unchecked", "-deprecation", "-optimize", "-Xcheckinit", "-encoding", "utf8"),
- scalacOptions <++= scalaVersion map {
- case v if v.startsWith("2.9") || v.startsWith("2.10") => Seq("-P:continuations:enable")
- case _ => Seq.empty
- },
- scalacOptions in Compile <++= scalaVersion map ({
- case v if v startsWith "2.10" => Seq("-language:implicitConversions", "-language:reflectiveCalls")
- case _ => Seq.empty
- }),
- javacOptions in compile ++= Seq("-target", "1.6", "-source", "1.6", "-Xlint:deprecation"),
- manifestSetting,
- autoCompilerPlugins := true,
- libraryDependencies <++= scalaVersion {
- case v if v.startsWith("2.9") || v.startsWith("2.10") => Seq(compilerPlugin("org.scala-lang.plugins" % "continuations" % v))
- case _ => Seq.empty
- },
- parallelExecution in Test := false,
- commands += Command.args("s", "") { (state, args) =>
- args.mkString(" ") ! state.log
- state
- },
- TaskKey[Unit]("gc", "runs garbage collector") <<= streams map { s =>
- s.log.info("requesting garbage collection")
- System.gc()
- }
- )
-
- val buildInfoConfig: Seq[Setting[_]] = buildInfoSettings ++ Seq(
- sourceGenerators in Compile <+= buildInfo,
- buildInfoKeys := Seq[BuildInfoKey](name, version, scalaVersion, sbtVersion),
- buildInfoPackage <<= organization(_ + ".client.async")
- )
-
- val defaultSettings =
- Defaults.defaultSettings ++ releaseSettings ++ buildInfoConfig ++ projectSettings ++ publishSettings ++ mavenCentralFrouFrou
-
-
- lazy val root = Project(
- id = "swagger-async-httpclient",
- base = file("."),
- settings = defaultSettings ++ Seq(
- libraryDependencies ++= Seq(
- "org.scalatra.rl" %% "rl" % "0.4.10",
- "org.slf4j" % "slf4j-api" % "1.7.7",
- "ch.qos.logback" % "logback-classic" % "1.1.2" % "provided",
- "org.json4s" %% "json4s-jackson" % "3.2.10",
- "com.googlecode.juniversalchardet" % "juniversalchardet" % "1.0.3",
- "eu.medsea.mimeutil" % "mime-util" % "2.1.3" exclude("org.slf4j", "slf4j-log4j12") exclude("log4j", "log4j"),
- "com.ning" % "async-http-client" % "1.8.14"
- ),
- libraryDependencies <+= scalaVersion {
- case "2.9.3" => "org.clapper" % "grizzled-slf4j_2.9.2" % "0.6.10" exclude("org.scala-lang", "scala-library")
- case v if v startsWith "2.9" => "org.clapper" %% "grizzled-slf4j" % "0.6.10"
- case v if v startsWith "2.10" => "com.typesafe.scala-logging" %% "scala-logging-slf4j" % "2.1.2"
- case v => "com.typesafe.scala-logging" %% "scala-logging" % "3.1.0"
- },
- libraryDependencies <++= scalaVersion {
- case v if v startsWith "2.9" => Seq("com.typesafe.akka" % "akka-actor" % "2.0.5")
- case v => Seq.empty
- },
- resolvers <++= scalaVersion {
- case v if v startsWith "2.9" => Seq("Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/")
- case v => Seq.empty
- },
- versionSpecificSourcesIn(Compile)
- )
- )
-}
diff --git a/project/plugins.sbt b/project/plugins.sbt
index 825fd38..7747411 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -1,5 +1,3 @@
-addSbtPlugin("com.github.gseitz" % "sbt-release" % "0.8.5")
-
-addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.3.2")
-
-addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.1.6")
+addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.7")
+addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0")
+addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.3.4")
diff --git a/sbt b/sbt
index 08e5882..218f371 100755
--- a/sbt
+++ b/sbt
@@ -1,25 +1,100 @@
#!/usr/bin/env bash
#
# A more capable sbt runner, coincidentally also called sbt.
-# Author: Paul Phillips
+# Author: Paul Phillips
+
+set -o pipefail
+
+declare -r sbt_release_version="0.13.16"
+declare -r sbt_unreleased_version="0.13.16"
+
+declare -r latest_213="2.13.0-M2"
+declare -r latest_212="2.12.4"
+declare -r latest_211="2.11.12"
+declare -r latest_210="2.10.7"
+declare -r latest_29="2.9.3"
+declare -r latest_28="2.8.2"
-# todo - make this dynamic
-declare -r sbt_release_version="0.13.6"
-declare -r sbt_unreleased_version="0.13.6"
declare -r buildProps="project/build.properties"
-declare sbt_jar sbt_dir sbt_create sbt_version
-declare scala_version sbt_explicit_version
-declare verbose noshare batch trace_level log_level
-declare sbt_saved_stty debugUs
+declare -r sbt_launch_ivy_release_repo="http://repo.typesafe.com/typesafe/ivy-releases"
+declare -r sbt_launch_ivy_snapshot_repo="https://repo.scala-sbt.org/scalasbt/ivy-snapshots"
+declare -r sbt_launch_mvn_release_repo="http://repo.scala-sbt.org/scalasbt/maven-releases"
+declare -r sbt_launch_mvn_snapshot_repo="http://repo.scala-sbt.org/scalasbt/maven-snapshots"
+
+declare -r default_jvm_opts_common="-Xms512m -Xmx1536m -Xss2m"
+declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy"
+
+declare sbt_jar sbt_dir sbt_create sbt_version sbt_script sbt_new
+declare sbt_explicit_version
+declare verbose noshare batch trace_level
+declare debugUs
+
+declare java_cmd="java"
+declare sbt_launch_dir="$HOME/.sbt/launchers"
+declare sbt_launch_repo
+
+# pull -J and -D options to give to java.
+declare -a java_args scalac_args sbt_commands residual_args
+
+# args to jvm/sbt via files or environment variables
+declare -a extra_jvm_opts extra_sbt_opts
echoerr () { echo >&2 "$@"; }
vlog () { [[ -n "$verbose" ]] && echoerr "$@"; }
+die () { echo "Aborting: $@" ; exit 1; }
+
+setTrapExit () {
+ # save stty and trap exit, to ensure echo is re-enabled if we are interrupted.
+ export SBT_STTY="$(stty -g 2>/dev/null)"
+
+ # restore stty settings (echo in particular)
+ onSbtRunnerExit() {
+ [ -t 0 ] || return
+ vlog ""
+ vlog "restoring stty: $SBT_STTY"
+ stty "$SBT_STTY"
+ }
+
+ vlog "saving stty: $SBT_STTY"
+ trap onSbtRunnerExit EXIT
+}
+
+# this seems to cover the bases on OSX, and someone will
+# have to tell me about the others.
+get_script_path () {
+ local path="$1"
+ [[ -L "$path" ]] || { echo "$path" ; return; }
+
+ local target="$(readlink "$path")"
+ if [[ "${target:0:1}" == "/" ]]; then
+ echo "$target"
+ else
+ echo "${path%/*}/$target"
+ fi
+}
+
+declare -r script_path="$(get_script_path "$BASH_SOURCE")"
+declare -r script_name="${script_path##*/}"
+
+init_default_option_file () {
+ local overriding_var="${!1}"
+ local default_file="$2"
+ if [[ ! -r "$default_file" && "$overriding_var" =~ ^@(.*)$ ]]; then
+ local envvar_file="${BASH_REMATCH[1]}"
+ if [[ -r "$envvar_file" ]]; then
+ default_file="$envvar_file"
+ fi
+ fi
+ echo "$default_file"
+}
+
+declare sbt_opts_file="$(init_default_option_file SBT_OPTS .sbtopts)"
+declare jvm_opts_file="$(init_default_option_file JVM_OPTS .jvmopts)"
-# spaces are possible, e.g. sbt.version = 0.13.0
build_props_sbt () {
[[ -r "$buildProps" ]] && \
- grep '^sbt\.version' "$buildProps" | tr '=' ' ' | awk '{ print $2; }'
+ grep '^sbt\.version' "$buildProps" | tr '=\r' ' ' | awk '{ print $2; }'
}
update_build_props_sbt () {
@@ -43,104 +118,87 @@ set_sbt_version () {
export sbt_version
}
-# restore stty settings (echo in particular)
-onSbtRunnerExit() {
- [[ -n "$sbt_saved_stty" ]] || return
- vlog ""
- vlog "restoring stty: $sbt_saved_stty"
- stty "$sbt_saved_stty"
- unset sbt_saved_stty
-}
-
-# save stty and trap exit, to ensure echo is reenabled if we are interrupted.
-trap onSbtRunnerExit EXIT
-sbt_saved_stty="$(stty -g 2>/dev/null)"
-vlog "Saved stty: $sbt_saved_stty"
+url_base () {
+ local version="$1"
-# this seems to cover the bases on OSX, and someone will
-# have to tell me about the others.
-get_script_path () {
- local path="$1"
- [[ -L "$path" ]] || { echo "$path" ; return; }
-
- local target="$(readlink "$path")"
- if [[ "${target:0:1}" == "/" ]]; then
- echo "$target"
- else
- echo "${path%/*}/$target"
- fi
-}
-
-die() {
- echo "Aborting: $@"
- exit 1
+ case "$version" in
+ 0.7.*) echo "http://simple-build-tool.googlecode.com" ;;
+ 0.10.* ) echo "$sbt_launch_ivy_release_repo" ;;
+ 0.11.[12]) echo "$sbt_launch_ivy_release_repo" ;;
+ 0.*-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]) # ie "*-yyyymmdd-hhMMss"
+ echo "$sbt_launch_ivy_snapshot_repo" ;;
+ 0.*) echo "$sbt_launch_ivy_release_repo" ;;
+ *-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]) # ie "*-yyyymmdd-hhMMss"
+ echo "$sbt_launch_mvn_snapshot_repo" ;;
+ *) echo "$sbt_launch_mvn_release_repo" ;;
+ esac
}
make_url () {
- version="$1"
+ local version="$1"
+
+ local base="${sbt_launch_repo:-$(url_base "$version")}"
case "$version" in
- 0.7.*) echo "http://simple-build-tool.googlecode.com/files/sbt-launch-0.7.7.jar" ;;
- 0.10.* ) echo "$sbt_launch_repo/org.scala-tools.sbt/sbt-launch/$version/sbt-launch.jar" ;;
- 0.11.[12]) echo "$sbt_launch_repo/org.scala-tools.sbt/sbt-launch/$version/sbt-launch.jar" ;;
- *) echo "$sbt_launch_repo/org.scala-sbt/sbt-launch/$version/sbt-launch.jar" ;;
+ 0.7.*) echo "$base/files/sbt-launch-0.7.7.jar" ;;
+ 0.10.* ) echo "$base/org.scala-tools.sbt/sbt-launch/$version/sbt-launch.jar" ;;
+ 0.11.[12]) echo "$base/org.scala-tools.sbt/sbt-launch/$version/sbt-launch.jar" ;;
+ 0.*) echo "$base/org.scala-sbt/sbt-launch/$version/sbt-launch.jar" ;;
+ *) echo "$base/org/scala-sbt/sbt-launch/$version/sbt-launch.jar" ;;
esac
}
-init_default_option_file () {
- local overriding_var="${!1}"
- local default_file="$2"
- if [[ ! -r "$default_file" && "$overriding_var" =~ ^@(.*)$ ]]; then
- local envvar_file="${BASH_REMATCH[1]}"
- if [[ -r "$envvar_file" ]]; then
- default_file="$envvar_file"
- fi
- fi
- echo "$default_file"
-}
-
-declare -r cms_opts="-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC"
-declare -r jit_opts="-XX:ReservedCodeCacheSize=256m -XX:+TieredCompilation"
-declare -r default_jvm_opts_common="-Xms512m -Xmx1536m -Xss2m $jit_opts $cms_opts"
-declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy"
-declare -r latest_28="2.8.2"
-declare -r latest_29="2.9.3"
-declare -r latest_210="2.10.4"
-declare -r latest_211="2.11.2"
+addJava () { vlog "[addJava] arg = '$1'" ; java_args+=("$1"); }
+addSbt () { vlog "[addSbt] arg = '$1'" ; sbt_commands+=("$1"); }
+addScalac () { vlog "[addScalac] arg = '$1'" ; scalac_args+=("$1"); }
+addResidual () { vlog "[residual] arg = '$1'" ; residual_args+=("$1"); }
-declare -r script_path="$(get_script_path "$BASH_SOURCE")"
-declare -r script_name="${script_path##*/}"
-
-# some non-read-onlies set with defaults
-declare java_cmd="java"
-declare sbt_opts_file="$(init_default_option_file SBT_OPTS .sbtopts)"
-declare jvm_opts_file="$(init_default_option_file JVM_OPTS .jvmopts)"
-declare sbt_launch_repo="http://typesafe.artifactoryonline.com/typesafe/ivy-releases"
+addResolver () { addSbt "set resolvers += $1"; }
+addDebugger () { addJava "-Xdebug" ; addJava "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=$1"; }
+setThisBuild () {
+ vlog "[addBuild] args = '$@'"
+ local key="$1" && shift
+ addSbt "set $key in ThisBuild := $@"
+}
+setScalaVersion () {
+ [[ "$1" == *"-SNAPSHOT" ]] && addResolver 'Resolver.sonatypeRepo("snapshots")'
+ addSbt "++ $1"
+}
+setJavaHome () {
+ java_cmd="$1/bin/java"
+ setThisBuild javaHome "_root_.scala.Some(file(\"$1\"))"
+ export JAVA_HOME="$1"
+ export JDK_HOME="$1"
+ export PATH="$JAVA_HOME/bin:$PATH"
+}
-# pull -J and -D options to give to java.
-declare -a residual_args
-declare -a java_args
-declare -a scalac_args
-declare -a sbt_commands
+getJavaVersion() { "$1" -version 2>&1 | grep -E -e '(java|openjdk) version' | awk '{ print $3 }' | tr -d \"; }
-# args to jvm/sbt via files or environment variables
-declare -a extra_jvm_opts extra_sbt_opts
+checkJava() {
+ # Warn if there is a Java version mismatch between PATH and JAVA_HOME/JDK_HOME
-# if set, use JAVA_HOME over java found in path
-[[ -e "$JAVA_HOME/bin/java" ]] && java_cmd="$JAVA_HOME/bin/java"
+ [[ -n "$JAVA_HOME" && -e "$JAVA_HOME/bin/java" ]] && java="$JAVA_HOME/bin/java"
+ [[ -n "$JDK_HOME" && -e "$JDK_HOME/lib/tools.jar" ]] && java="$JDK_HOME/bin/java"
-# directory to store sbt launchers
-declare sbt_launch_dir="$HOME/.sbt/launchers"
-[[ -d "$sbt_launch_dir" ]] || mkdir -p "$sbt_launch_dir"
-[[ -w "$sbt_launch_dir" ]] || sbt_launch_dir="$(mktemp -d -t sbt_extras_launchers.XXXXXX)"
+ if [[ -n "$java" ]]; then
+ pathJavaVersion=$(getJavaVersion java)
+ homeJavaVersion=$(getJavaVersion "$java")
+ if [[ "$pathJavaVersion" != "$homeJavaVersion" ]]; then
+ echoerr "Warning: Java version mismatch between PATH and JAVA_HOME/JDK_HOME, sbt will use the one in PATH"
+ echoerr " Either: fix your PATH, remove JAVA_HOME/JDK_HOME or use -java-home"
+ echoerr " java version from PATH: $pathJavaVersion"
+ echoerr " java version from JAVA_HOME/JDK_HOME: $homeJavaVersion"
+ fi
+ fi
+}
java_version () {
- local version=$("$java_cmd" -version 2>&1 | grep -e 'java version' | awk '{ print $3 }' | tr -d \")
+ local version=$(getJavaVersion "$java_cmd")
vlog "Detected Java version: $version"
echo "${version:2:1}"
}
-# MaxPermSize critical on pre-8 jvms but incurs noisy warning on 8+
+# MaxPermSize critical on pre-8 JVMs but incurs noisy warning on 8+
default_jvm_opts () {
local v="$(java_version)"
if [[ $v -ge 8 ]]; then
@@ -173,16 +231,23 @@ execRunner () {
vlog ""
}
- [[ -n "$batch" ]] && exec /dev/null; then
- curl --fail --silent "$url" --output "$jar"
+ curl --fail --silent --location "$url" --output "$jar"
elif which wget >/dev/null; then
- wget --quiet -O "$jar" "$url"
+ wget -q -O "$jar" "$url"
fi
} && [[ -r "$jar" ]]
}
acquire_sbt_jar () {
- sbt_url="$(jar_url "$sbt_version")"
- sbt_jar="$(jar_file "$sbt_version")"
-
- [[ -r "$sbt_jar" ]] || download_url "$sbt_url" "$sbt_jar"
+ {
+ sbt_jar="$(jar_file "$sbt_version")"
+ [[ -r "$sbt_jar" ]]
+ } || {
+ sbt_jar="$HOME/.ivy2/local/org.scala-sbt/sbt-launch/$sbt_version/jars/sbt-launch.jar"
+ [[ -r "$sbt_jar" ]]
+ } || {
+ sbt_jar="$(jar_file "$sbt_version")"
+ download_url "$(make_url "$sbt_version")" "$sbt_jar"
+ }
}
usage () {
+ set_sbt_version
cat < Turn on JVM debugging, open at the given port.
-batch Disable interactive mode
-prompt Set the sbt prompt; in expr, 's' is the State and 'e' is Extracted
+ -script Run the specified file as a scala script
# sbt version (default: sbt.version from $buildProps if present, otherwise $sbt_release_version)
-sbt-force-latest force the use of the latest release of sbt: $sbt_release_version
-sbt-version use the specified version of sbt (default: $sbt_release_version)
-sbt-dev use the latest pre-release version of sbt: $sbt_unreleased_version
-sbt-jar use the specified jar as the sbt launcher
- -sbt-launch-dir directory to hold sbt launchers (default: ~/.sbt/launchers)
- -sbt-launch-repo repo url for downloading sbt launcher jar (default: $sbt_launch_repo)
+ -sbt-launch-dir directory to hold sbt launchers (default: $sbt_launch_dir)
+ -sbt-launch-repo repo url for downloading sbt launcher jar (default: $(url_base "$sbt_version"))
# scala version (default: as chosen by sbt)
-28 use $latest_28
-29 use $latest_29
-210 use $latest_210
-211 use $latest_211
+ -212 use $latest_212
+ -213 use $latest_213
-scala-home use the scala build at the specified directory
-scala-version use the specified version of scala
-binary-version use the specified scala version when searching for dependencies
@@ -280,42 +355,7 @@ runner with the -x option.
EOM
}
-addJava () {
- vlog "[addJava] arg = '$1'"
- java_args=( "${java_args[@]}" "$1" )
-}
-addSbt () {
- vlog "[addSbt] arg = '$1'"
- sbt_commands=( "${sbt_commands[@]}" "$1" )
-}
-setThisBuild () {
- vlog "[addBuild] args = '$@'"
- local key="$1" && shift
- addSbt "set $key in ThisBuild := $@"
-}
-
-addScalac () {
- vlog "[addScalac] arg = '$1'"
- scalac_args=( "${scalac_args[@]}" "$1" )
-}
-addResidual () {
- vlog "[residual] arg = '$1'"
- residual_args=( "${residual_args[@]}" "$1" )
-}
-addResolver () {
- addSbt "set resolvers += $1"
-}
-addDebugger () {
- addJava "-Xdebug"
- addJava "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=$1"
-}
-setScalaVersion () {
- [[ "$1" == *"-SNAPSHOT" ]] && addResolver 'Resolver.sonatypeRepo("snapshots")'
- addSbt "++ $1"
-}
-
-process_args ()
-{
+process_args () {
require_arg () {
local type="$1"
local opt="$2"
@@ -327,10 +367,10 @@ process_args ()
}
while [[ $# -gt 0 ]]; do
case "$1" in
- -h|-help) usage; exit 1 ;;
+ -h|-help) usage; exit 0 ;;
-v) verbose=true && shift ;;
-d) addSbt "--debug" && shift ;;
- -w) addSbt "--warn" && shift ;;
+ -w) addSbt "--warn" && shift ;;
-q) addSbt "--error" && shift ;;
-x) debugUs=true && shift ;;
-trace) require_arg integer "$1" "$2" && trace_level="$2" && shift 2 ;;
@@ -340,10 +380,11 @@ process_args ()
-sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;;
-sbt-dir) require_arg path "$1" "$2" && sbt_dir="$2" && shift 2 ;;
-debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;;
- -offline) addSbt "set offline := true" && shift ;;
+ -offline) addSbt "set offline in Global := true" && shift ;;
-jvm-debug) require_arg port "$1" "$2" && addDebugger "$2" && shift 2 ;;
-batch) batch=true && shift ;;
-prompt) require_arg "expr" "$1" "$2" && setThisBuild shellPrompt "(s => { val e = Project.extract(s) ; $2 })" && shift 2 ;;
+ -script) require_arg file "$1" "$2" && sbt_script="$2" && addJava "-Dsbt.main.class=sbt.ScriptMain" && shift 2 ;;
-sbt-create) sbt_create=true && shift ;;
-sbt-jar) require_arg path "$1" "$2" && sbt_jar="$2" && shift 2 ;;
@@ -354,8 +395,8 @@ process_args ()
-sbt-launch-repo) require_arg path "$1" "$2" && sbt_launch_repo="$2" && shift 2 ;;
-scala-version) require_arg version "$1" "$2" && setScalaVersion "$2" && shift 2 ;;
-binary-version) require_arg version "$1" "$2" && setThisBuild scalaBinaryVersion "\"$2\"" && shift 2 ;;
- -scala-home) require_arg path "$1" "$2" && setThisBuild scalaHome "Some(file(\"$2\"))" && shift 2 ;;
- -java-home) require_arg path "$1" "$2" && java_cmd="$2/bin/java" && shift 2 ;;
+ -scala-home) require_arg path "$1" "$2" && setThisBuild scalaHome "_root_.scala.Some(file(\"$2\"))" && shift 2 ;;
+ -java-home) require_arg path "$1" "$2" && setJavaHome "$2" && shift 2 ;;
-sbt-opts) require_arg path "$1" "$2" && sbt_opts_file="$2" && shift 2 ;;
-jvm-opts) require_arg path "$1" "$2" && jvm_opts_file="$2" && shift 2 ;;
@@ -366,7 +407,9 @@ process_args ()
-29) setScalaVersion "$latest_29" && shift ;;
-210) setScalaVersion "$latest_210" && shift ;;
-211) setScalaVersion "$latest_211" && shift ;;
-
+ -212) setScalaVersion "$latest_212" && shift ;;
+ -213) setScalaVersion "$latest_213" && shift ;;
+ new) sbt_new=true && : ${sbt_explicit_version:=$sbt_release_version} && addResidual "$1" && shift ;;
*) addResidual "$1" && shift ;;
esac
done
@@ -377,8 +420,10 @@ process_args "$@"
# skip #-styled comments and blank lines
readConfigFile() {
- while read line; do
- [[ $line =~ ^# ]] || [[ -z $line ]] || echo "$line"
+ local end=false
+ until $end; do
+ read || end=true
+ [[ $REPLY =~ ^# ]] || [[ -z $REPLY ]] || echo "$REPLY"
done < "$1"
}
@@ -403,6 +448,8 @@ argumentCount=$#
# set sbt version
set_sbt_version
+checkJava
+
# only exists in 0.12+
setTraceLevel() {
case "$sbt_version" in
@@ -415,19 +462,21 @@ setTraceLevel() {
[[ ${#scalac_args[@]} -eq 0 ]] || addSbt "set scalacOptions in ThisBuild += \"${scalac_args[@]}\""
# Update build.properties on disk to set explicit version - sbt gives us no choice
-[[ -n "$sbt_explicit_version" ]] && update_build_props_sbt "$sbt_explicit_version"
+[[ -n "$sbt_explicit_version" && -z "$sbt_new" ]] && update_build_props_sbt "$sbt_explicit_version"
vlog "Detected sbt version $sbt_version"
-[[ -n "$scala_version" ]] && vlog "Overriding scala version to $scala_version"
-
-# no args - alert them there's stuff in here
-(( argumentCount > 0 )) || {
- vlog "Starting $script_name: invoke with -help for other options"
- residual_args=( shell )
-}
+if [[ -n "$sbt_script" ]]; then
+ residual_args=( $sbt_script ${residual_args[@]} )
+else
+ # no args - alert them there's stuff in here
+ (( argumentCount > 0 )) || {
+ vlog "Starting $script_name: invoke with -help for other options"
+ residual_args=( shell )
+ }
+fi
-# verify this is an sbt dir or -create was given
-[[ -r ./build.sbt || -d ./project || -n "$sbt_create" ]] || {
+# verify this is an sbt dir, -create was given or user attempts to run a scala script
+[[ -r ./build.sbt || -d ./project || -n "$sbt_create" || -n "$sbt_script" || -n "$sbt_new" ]] || {
cat < T): Future[T] = {
- val fut = Promise[T]()
- try {
- val r = fn
- r match {
- case t: Throwable => fut.complete(Failure(t))
- case s => fut.complete(Success(s))
- }
- } catch {
- case t: Throwable => fut.complete(Failure(t))
- }
- fut.future
- }
-}
diff --git a/src/main/scala_2.11/io/swagger/client/RestClient.scala b/src/main/scala_2.11/io/swagger/client/RestClient.scala
deleted file mode 100644
index 464f085..0000000
--- a/src/main/scala_2.11/io/swagger/client/RestClient.scala
+++ /dev/null
@@ -1,446 +0,0 @@
-package io.swagger.client
-
-import java.io.File
-import java.net.URI
-import java.nio.charset.Charset
-import java.text.SimpleDateFormat
-import java.util.concurrent.ConcurrentHashMap
-import java.util.concurrent.atomic.AtomicLong
-import java.util.{Date, Locale, TimeZone, concurrent => juc}
-
-import com.ning.http.client._
-import com.ning.http.client.cookie.{Cookie => AhcCookie}
-import com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig
-import io.swagger.client.async.BuildInfo
-import org.jboss.netty.channel.socket.nio.{NioClientSocketChannelFactory, NioWorkerPool}
-import org.jboss.netty.util.{HashedWheelTimer, Timer}
-import rl.Imports._
-import rl.{MapQueryString, UrlCodingUtils}
-
-import scala.collection.JavaConverters._
-import scala.concurrent.duration._
-import scala.concurrent.{ExecutionContext, Future, Promise}
-import scala.io.Codec
-import scala.util.Failure
-
-object RestClient {
-
- private val threadIds = new AtomicLong()
-
- private lazy val factory = new juc.ThreadFactory {
- def newThread(runnable: Runnable): Thread = {
- val thread = new Thread(runnable)
- thread.setName("swagger-client-thread-" + threadIds.incrementAndGet())
- thread.setDaemon(true)
- thread
- }
- }
-
- val DefaultUserAgent = s"Reverb SwaggerClient / ${BuildInfo.version}"
-
- private implicit def stringWithExt(s: String) = new {
- def isBlank = s == null || s.trim.isEmpty
- def nonBlank = !isBlank
- def blankOption = if (isBlank) None else Option(s)
- }
-
- case class CookieOptions( domain : String = "",
- path : String = "",
- maxAge : Int = -1,
- secure : Boolean = false,
- comment : String = "",
- httpOnly: Boolean = false,
- version : Int = 0,
- encoding: String = "UTF-8")
-
- trait HttpCookie {
- implicit def cookieOptions: CookieOptions
- def name: String
- def value: String
-
- }
-
- case class RequestCookie(name: String, value: String, cookieOptions: CookieOptions = CookieOptions()) extends HttpCookie
-
- object DateUtil {
- @volatile private[this] var _currentTimeMillis: Option[Long] = None
- def currentTimeMillis = _currentTimeMillis getOrElse System.currentTimeMillis
- def currentTimeMillis_=(ct: Long) = _currentTimeMillis = Some(ct)
- def freezeTime() = _currentTimeMillis = Some(System.currentTimeMillis())
- def unfreezeTime() = _currentTimeMillis = None
- def formatDate(date: Date, format: String, timeZone: TimeZone = TimeZone.getTimeZone("GMT")) = {
- val df = new SimpleDateFormat(format)
- df.setTimeZone(timeZone)
- df.format(date)
- }
- }
-
-
- case class Cookie(name: String, value: String)(implicit val cookieOptions: CookieOptions = CookieOptions()) extends HttpCookie {
-
- private def ensureDotDomain =
- (if (!cookieOptions.domain.startsWith(".")) "." + cookieOptions.domain else cookieOptions.domain).toLowerCase(Locale.ENGLISH)
-
- def toCookieString = {
- val sb = new StringBuffer
- sb append name append "="
- sb append value
-
- if(cookieOptions.domain.nonBlank && cookieOptions.domain != "localhost")
- sb.append("; Domain=").append(ensureDotDomain)
-
- val pth = cookieOptions.path
- if(pth.nonBlank) sb append "; Path=" append (if(!pth.startsWith("/")) {
- "/" + pth
- } else { pth })
-
- if(cookieOptions.comment.nonBlank) sb append ("; Comment=") append cookieOptions.comment
-
- appendMaxAge(sb, cookieOptions.maxAge, cookieOptions.version)
-
- if (cookieOptions.secure) sb append "; Secure"
- if (cookieOptions.httpOnly) sb append "; HttpOnly"
- sb.toString
- }
- private[this] def appendMaxAge(sb: StringBuffer, maxAge: Int, version: Int) = {
- val dateInMillis = maxAge match {
- case a if a < 0 => None // we don't do anything for max-age when it's < 0 then it becomes a session cookie
- case 0 => Some(0L) // Set the date to the min date for the system
- case a => Some(DateUtil.currentTimeMillis + a * 1000)
- }
-
- // This used to be Max-Age but IE is not always very happy with that
- // see: http://mrcoles.com/blog/cookies-max-age-vs-expires/
- // see Q1: http://blogs.msdn.com/b/ieinternals/archive/2009/08/20/wininet-ie-cookie-internals-faq.aspx
- val bOpt = dateInMillis map (ms => appendExpires(sb, new Date(ms)))
- val agedOpt = if (version > 0) bOpt map (_.append("; Max-Age=").append(maxAge)) else bOpt
- agedOpt getOrElse sb
- }
-
- private[this] def appendExpires(sb: StringBuffer, expires: Date) =
- sb append "; Expires=" append formatExpires(expires)
-
- private[this] def formatExpires(date: Date) = DateUtil.formatDate(date, "EEE, dd MMM yyyy HH:mm:ss zzz")
-
- }
-
-
- class CookieJar(private val reqCookies: Map[String, RequestCookie]) {
- private val cookies = new ConcurrentHashMap[String, HttpCookie].asScala ++ reqCookies
-
- def get(key: String) = cookies.get(key) filter (_.cookieOptions.maxAge != 0) map (_.value)
-
- def apply(key: String) = get(key) getOrElse (throw new Exception("No cookie could be found for the specified key [%s]" format key))
-
- def update(name: String, value: String)(implicit cookieOptions: CookieOptions=CookieOptions()) = {
- cookies += name -> Cookie(name, value)(cookieOptions)
- }
-
- def set(name: String, value: String)(implicit cookieOptions: CookieOptions=CookieOptions()) = {
- this.update(name, value)(cookieOptions)
- }
-
- def delete(name: String)(implicit cookieOptions: CookieOptions = CookieOptions(maxAge = 0)) {
- this.update(name, "")(cookieOptions.copy(maxAge = 0))
- }
-
- def +=(keyValuePair: (String, String))(implicit cookieOptions: CookieOptions = CookieOptions()) = {
- this.update(keyValuePair._1, keyValuePair._2)(cookieOptions)
- }
-
- def -=(key: String)(implicit cookieOptions: CookieOptions = CookieOptions(maxAge = 0)) {
- delete(key)(cookieOptions)
- }
-
- def size = cookies.size
-
- def foreach[U](fn: (HttpCookie) => U) = cookies foreach { case (_, v) => fn(v) }
-
- private[client] def responseCookies = cookies.values collect { case c: Cookie => c }
-
- override def toString: String = cookies.toString()
- }
-
-
- class RestClientResponse(response: Response) extends ClientResponse {
- val cookies = (response.getCookies.asScala map { cookie =>
- val cko = CookieOptions(cookie.getDomain, cookie.getPath, cookie.getMaxAge)
- cookie.getName -> Cookie(cookie.getName, cookie.getValue)(cko)
- }).toMap
-
- val headers = (response.getHeaders.keySet().asScala map { k => k -> response.getHeaders(k).asScala.toSeq}).toMap
-
- val status = ResponseStatus(response.getStatusCode, response.getStatusText)
-
- val contentType = response.getContentType
-
- val inputStream = response.getResponseBodyAsStream
-
- val uri = response.getUri
-
- def body = response.getResponseBody(charset getOrElse "UTF-8")
-
- def mediaType: Option[String] = headers.get("Content-Type") flatMap { _.headOption }
-
- def charset: Option[String] =
- for {
- ct <- mediaType
- charset <- ct.split(";").drop(1).headOption
- } yield charset.toUpperCase.replace("CHARSET=", "").trim
- }
-
- trait Defaults {
- def builder: AsyncHttpClientConfig.Builder
- def timer: Timer
- }
-
- private object InternalDefaults {
- /** true if we think we're runing un-forked in an sbt-interactive session */
- val inTrapExit = (
- for (group ← Option(Thread.currentThread.getThreadGroup))
- yield group.getName == "trap.exit").getOrElse(false)
-
- /** Sets a user agent, no timeout for requests */
- object BasicDefaults extends Defaults {
- lazy val timer = new HashedWheelTimer()
- def builder = (new AsyncHttpClientConfig.Builder()
- setAllowPoolingConnection true
- setRequestTimeoutInMs 45000
- setCompressionEnabled true
- setFollowRedirects false
- setMaximumConnectionsPerHost 200
- setUserAgent DefaultUserAgent
- setMaxRequestRetry 0)
- }
-
- /** Uses daemon threads and tries to exit cleanly when running in sbt */
- object SbtProcessDefaults extends Defaults {
- def builder = {
- val shuttingDown = new juc.atomic.AtomicBoolean(false)
- /** daemon threads that also shut down everything when interrupted! */
- lazy val interruptThreadFactory = new juc.ThreadFactory {
- def newThread(runnable: Runnable) = {
- new Thread(runnable) {
- setDaemon(true)
- setName("bragi-client-thread-" + threadIds.incrementAndGet())
- override def interrupt() {
- shutdown()
- super.interrupt()
- }
- }
- }
- }
- lazy val nioClientSocketChannelFactory = {
- val workerCount = 2 * Runtime.getRuntime().availableProcessors()
- new NioClientSocketChannelFactory(
- juc.Executors.newCachedThreadPool(interruptThreadFactory),
- 1,
- new NioWorkerPool(
- juc.Executors.newCachedThreadPool(interruptThreadFactory),
- workerCount),
- timer)
- }
-
- def shutdown() {
- if (shuttingDown.compareAndSet(false, true)) {
- nioClientSocketChannelFactory.releaseExternalResources()
- }
- }
-
- BasicDefaults.builder.setAsyncHttpClientProviderConfig(
- new NettyAsyncHttpProviderConfig().addProperty(
- NettyAsyncHttpProviderConfig.SOCKET_CHANNEL_FACTORY,
- nioClientSocketChannelFactory))
- }
- lazy val timer = new HashedWheelTimer(factory)
- }
- }
-}
-
-class RestClient(config: SwaggerConfig) extends TransportClient with Logging {
-
- import io.swagger.client.RestClient._
- protected def underlying: Defaults = {
- if (InternalDefaults.inTrapExit) InternalDefaults.SbtProcessDefaults
- else InternalDefaults.BasicDefaults
- }
- protected val locator: ServiceLocator = config.locator
- protected val clientConfig: AsyncHttpClientConfig = (underlying.builder
- setUserAgent config.userAgent
- setRequestTimeoutInMs config.idleTimeout.toMillis.toInt
- setConnectionTimeoutInMs config.connectTimeout.toMillis.toInt
- setCompressionEnabled config.enableCompression // enable content-compression
- setAllowPoolingConnection true // enable http keep-alive
- setFollowRedirects config.followRedirects).build()
-
- import io.swagger.client.StringHttpMethod._
- implicit val execContext = ExecutionContext.fromExecutorService(clientConfig.executorService())
-
- private[this] val mimes = new Mimes with Logging {
- protected def warn(message: String) = logger.warn(message)
- }
-
- private[this] val cookies = new CookieJar(Map.empty)
-
- protected def createClient() = new AsyncHttpClient(clientConfig)
-
- private[this] val client = createClient()
-
- private[this] def createRequest(method: String): String ⇒ AsyncHttpClient#BoundRequestBuilder = {
- method.toUpperCase(Locale.ENGLISH) match {
- case `GET` ⇒ client.prepareGet _
- case `POST` ⇒ client.preparePost _
- case `PUT` ⇒ client.preparePut _
- case `DELETE` ⇒ client.prepareDelete _
- case `HEAD` ⇒ client.prepareHead _
- case `OPTIONS` ⇒ client.prepareOptions _
- case `CONNECT` ⇒ client.prepareConnect _
- }
- }
-
- private[this] def addTimeout(timeout: Duration)(req: AsyncHttpClient#BoundRequestBuilder) = {
- if (timeout.isFinite()) {
- val prc = new PerRequestConfig()
- prc.setRequestTimeoutInMs(timeout.toMillis.toInt)
- req.setPerRequestConfig(prc)
- }
- req
- }
-
- private[this] def addParameters(method: String, params: Iterable[(String, String)], isMultipart: Boolean = false, charset: Charset = Codec.UTF8.charSet)(req: AsyncHttpClient#BoundRequestBuilder) = {
- method.toUpperCase(Locale.ENGLISH) match {
- case `GET` | `DELETE` | `HEAD` | `OPTIONS` ⇒ params foreach { case (k, v) ⇒ req addQueryParameter (k, v) }
- case `PUT` | `POST` | `PATCH` ⇒ {
- if (!isMultipart)
- if (req.build().getHeaders.getFirstValue("Content-Type").startsWith("application/x-www-form-urlencoded"))
- params foreach { case (k, v) ⇒ req addParameter (k, v) }
- else
- params foreach { case (k, v) => req addQueryParameter(k, v) }
- else {
- params foreach { case (k, v) => req addBodyPart new StringPart(k, v, charset.name)}
- }
- }
- case _ ⇒ // we don't care, carry on
- }
- req
- }
-
- private[this] def addHeaders(headers: Iterable[(String, String)], files: Iterable[(String, File)])(req: AsyncHttpClient#BoundRequestBuilder) = {
- headers foreach { case (k, v) => req.addHeader(k, v) }
- if (!Map(headers.map(kv => kv._1.toUpperCase -> kv._2).toSeq:_*).contains("CONTENT-TYPE"))
- req.setHeader("Content-Type", defaultWriteContentType(files)("Content-Type"))
- req
- }
-
- private[this] def addFiles(files: Iterable[(String, File)], isMultipart: Boolean)(req: AsyncHttpClient#BoundRequestBuilder) = {
- if (isMultipart) {
- files foreach { case (nm, file) =>
- req.addBodyPart(new FilePart(nm, file, mimes(file), FileCharset(file).name))
- }
- }
- req
- }
-
- private[this] def addCookies(req: AsyncHttpClient#BoundRequestBuilder) = {
- cookies foreach { cookie =>
- val ahcCookie = AhcCookie.newValidCookie(
- cookie.name,
- cookie.value,
- cookie.cookieOptions.domain,
- cookie.value,
- cookie.cookieOptions.path,
- -1,
- cookie.cookieOptions.maxAge,
- cookie.cookieOptions.secure,
- cookie.cookieOptions.httpOnly)
- req.addCookie(ahcCookie)
- }
- req
- }
-
- private[this] def addQuery(u: URI)(req: AsyncHttpClient#BoundRequestBuilder) = {
- u.getQuery.blankOption foreach { uu =>
- rl.QueryString(uu) match {
- case m: MapQueryString => m.value foreach { case (k, v) => v foreach { req.addQueryParameter(k, _) } }
- case _ =>
- }
- }
- req
- }
-
- private[this] val allowsBody = Vector(PUT, POST, PATCH)
-
-
- private[this] def addBody(method: String, body: String)(req: AsyncHttpClient#BoundRequestBuilder) = {
- if (allowsBody.contains(method.toUpperCase(Locale.ENGLISH)) && body.nonBlank) req.setBody(body)
- req
- }
-
-
- private[this] def requestFiles(params: Iterable[(String, Any)]) = params collect { case (k, v: File) => k -> v }
- private[this] def paramsFrom(params: Iterable[(String, Any)]) = params collect {
- case (k, v: String) => k -> v
- case (k, null) => k -> ""
- case (k, v) => k -> v.toString
- }
- private[this] def isMultipartRequest(method: String, headers: Iterable[(String, String)], files: Iterable[(String, File)]) = {
- allowsBody.contains(method.toUpperCase(Locale.ENGLISH)) && {
- val ct = (defaultWriteContentType(files) ++ headers)("Content-Type")
- ct.toLowerCase(Locale.ENGLISH).startsWith("multipart/form-data")
- }
- }
-
- private[this] def requestUri(base: URI, u: URI) = if (u.isAbsolute) u else {
- // There is no constructor on java.net.URI that will not encode the path
- // except for the one where you pass in a uri as string so we're concatenating ourselves
- val prt = base.getPort
- val b =
- if (prt > 0 && prt != 80 && prt != 443) "%s://%s:%d".format(base.getScheme, base.getHost, prt)
- else "%s://%s".format(base.getScheme, base.getHost)
- val p = base.getRawPath + u.getRawPath.blankOption.getOrElse("/")
- val q = u.getRawQuery.blankOption.map("?"+_).getOrElse("")
- val f = u.getRawFragment.blankOption.map("#"+_).getOrElse("")
- URI.create(b+p+q+f)
- }
-
- def submit(method: String, uri: String, params: Iterable[(String, Any)], headers: Iterable[(String, String)], body: String = "", timeout: Duration = 90.seconds): Future[RestClientResponse] = {
- val u = URI.create(if (UrlCodingUtils.needsUrlEncoding(uri)) uri.urlEncode else uri).normalize()
- val files = requestFiles(params)
- val isMultipart = isMultipartRequest(method, headers, files)
- locator.pickOneAsUri(config.name, "") flatMap { opt =>
- if (opt.isEmpty) sys.error("No host could be found for %s".format(config.name))
- else {
- val baseUrl = opt.get
- (createRequest(method)
- andThen addTimeout(timeout)
- andThen addHeaders(headers, files)
- andThen addCookies
- andThen addParameters(method, paramsFrom(params), isMultipart)
- andThen addQuery(u)
- andThen addBody(method, body)
- andThen addFiles(files, isMultipart)
- andThen executeRequest)(requestUri(URI.create(baseUrl).normalize(), u).toASCIIString)
- }
- }
- }
-
- private[this] def executeRequest(req: AsyncHttpClient#BoundRequestBuilder): Future[RestClientResponse] = {
- logger.debug("Requesting:\n" + req.build())
- val promise = Promise[RestClientResponse]()
- req.execute(new AsyncCompletionHandler[Promise[RestClientResponse]] {
- override def onThrowable(t: Throwable) = promise.complete(Failure(t))
- def onCompleted(response: Response) = {
- logger.debug(s"Got response [${response.getStatusCode} ${response.getStatusText}}] for request to ${req.build().getUrl}.\n$response")
- promise.success(new RestClientResponse(response))
- }
- })
- promise.future
- }
-
- private[this] def defaultWriteContentType(files: Iterable[(String, File)]) = {
- val value = if (files.nonEmpty) "multipart/form-data" else config.contentType.headerValue
- Map("Content-Type" -> value)
- }
-
- def close() = client.closeAsynchronously()
-}
diff --git a/src/main/scala_2.11/io/swagger/client/ServiceLocator.scala b/src/main/scala_2.11/io/swagger/client/ServiceLocator.scala
deleted file mode 100644
index 9e1912e..0000000
--- a/src/main/scala_2.11/io/swagger/client/ServiceLocator.scala
+++ /dev/null
@@ -1,126 +0,0 @@
-package io.swagger.client
-
-import scala.concurrent.{Await, Future, ExecutionContext}
-import scala.concurrent.duration._
-import scala.collection.concurrent.TrieMap
-import language.postfixOps
-import java.net.URI
-import java.util.concurrent.atomic.AtomicLong
-
-/**
- * A trait for a load balancing strategy.
- * It takes a set of hosts and returns a single host
- * from the Set
- */
-trait HostPicker {
- /**
- * Pick a host from the provided list of services
- * @param hosts The hosts to pick from
- * @return A Future with an Option that contains the host if there was one.
- */
- def apply(hosts: Set[String], serviceName: Option[String])(implicit executionContext: ExecutionContext): Future[Option[String]]
-}
-
-object HeadHostPicker extends HostPicker {
- def apply(hosts: Set[String], serviceName: Option[String] = None)(implicit executionContext: ExecutionContext): Future[Option[String]] = {
- Future.successful(hosts.headOption)
- }
-}
-
-object RandomHostPicker extends HostPicker {
- private[this] val rand = new util.Random()
- def apply(hosts: Set[String], serviceName: Option[String] = None)(implicit executionContext: ExecutionContext): Future[Option[String]] = {
- Future.successful(if (hosts.nonEmpty) Some(hosts.toList(rand.nextInt(hosts.size))) else None)
- }
-}
-
-object GlobalRoundRobinHostPicker extends HostPicker {
- private[this] val pickers = TrieMap.empty[String, RoundRobinHostPicker]
- private[this] val default = new RoundRobinHostPicker
-
- def apply(
- hosts: Set[String],
- serviceName: Option[String])(
- implicit executionContext: ExecutionContext): Future[Option[String]] = {
-
- val roundRobinPicker = serviceName map { name =>
- pickers.getOrElseUpdate(name, new RoundRobinHostPicker)
- } getOrElse(default)
-
- roundRobinPicker(hosts, None)
- }
-}
-
-final class RoundRobinHostPicker extends HostPicker {
- // Start at -1 so that the first call to incrementAndGet returns 0
- private[this] val counter = new AtomicLong(-1)
-
- def apply(hosts: Set[String], serviceName: Option[String] = None)(implicit executionContext: ExecutionContext): Future[Option[String]] = {
- Future.successful {
- val sortedHosts = hosts.toVector.sorted
-
- if (sortedHosts.length == 0) {
- None
- } else {
- // This cast is okay because vector.length is an Int.
- val index = (counter.incrementAndGet() % sortedHosts.length).toInt
- Some(sortedHosts(index))
- }
- }
- }
-}
-
-trait ServiceLocator {
- implicit protected def executionContext: ExecutionContext
- def locate(name: String): Future[Set[String]]
-
- def locateBlocking(name: String, atMost: FiniteDuration = 20 seconds): Set[String] = {
- Await.result(locate(name), atMost)
- }
-
- def pickOne(
- name: String,
- picker: HostPicker = GlobalRoundRobinHostPicker): Future[Option[String]]
-
- def pickOneBlocking(
- name: String,
- picker: HostPicker = GlobalRoundRobinHostPicker,
- atMost: FiniteDuration = 20 seconds): Option[String] = {
-
- Await.result(pickOne(name, picker), atMost)
- }
-
- def locateAsUris(name: String, path: String): Future[Set[String]]
-
- def locateAsUrisBlocking(
- name: String,
- path: String,
- atMost: FiniteDuration = 20 seconds): Set[String] = {
-
- Await.result(locateAsUris(name, path), atMost)
- }
-
- def pickOneAsUri(
- name: String,
- path: String,
- picker: HostPicker = GlobalRoundRobinHostPicker): Future[Option[String]]
-
- def pickOneAsUriBlocking(
- name: String,
- path: String,
- picker: HostPicker = GlobalRoundRobinHostPicker,
- atMost: FiniteDuration = 20 seconds): Option[String] = {
-
- Await.result(pickOneAsUri(name, path, picker), atMost)
- }
-}
-
-case class BaseUrl(url: URI)(implicit protected val executionContext: ExecutionContext = ExecutionContext.global) extends ServiceLocator {
- private[this] val withoutScheme = url.getHost
- private[this] val withScheme = url.getScheme + "://" + url.getAuthority + stripTrailingSlash(url.getPath)
- def locate(name: String): Future[Set[String]] = Future.successful(Set(withoutScheme))
- def pickOne(name: String, picker: HostPicker): Future[Option[String]] = Future.successful(Some(withoutScheme))
- def locateAsUris(name: String, path: String): Future[Set[String]] = Future.successful(Set(withScheme))
- def pickOneAsUri(name: String, path: String, picker: HostPicker): Future[Option[String]] = Future.successful(Some(withScheme))
- private def stripTrailingSlash(s: String): String = if (s endsWith "/") s.substring(0, s.length - 1) else s
-}
diff --git a/src/main/scala_2.11/io/swagger/client/SwaggerConfig.scala b/src/main/scala_2.11/io/swagger/client/SwaggerConfig.scala
deleted file mode 100644
index 8f7d5d2..0000000
--- a/src/main/scala_2.11/io/swagger/client/SwaggerConfig.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package io.swagger.client
-
-import scala.concurrent.duration._
-import java.io.StringWriter
-import org.json4s.jackson.JsonMethods
-import org.json4s._
-import org.json4s.Xml._
-import java.net.URI
-
-object SwaggerConfig {
-
-
- private case class DefaultSwaggerConfig(
- locator: ServiceLocator,
- override val userAgent: String = RestClient.DefaultUserAgent,
- override val idleTimeout: Duration = 5.minutes,
- override val connectTimeout: Duration = 5.seconds,
- override val maxMessageSize: Int = 8912,
- override val enableCompression: Boolean = true,
- override val followRedirects: Boolean = true,
- override val identity: String = "0",
- override val name: String = "no-name",
- override val contentType: ContentType = ContentType("json", "application/json;charset=utf-8")) extends SwaggerConfig
-
- def forUrl(
- baseUrl: URI,
- userAgent: String = RestClient.DefaultUserAgent,
- idleTimeout: Duration = 5.minutes,
- connectTimeout: Duration = 5.seconds,
- maxMessageSize: Int = 8912,
- enableCompression: Boolean = true,
- followRedirects: Boolean = true,
- identity: String = "0"): SwaggerConfig =
- new DefaultSwaggerConfig(BaseUrl(baseUrl), userAgent, idleTimeout, connectTimeout, maxMessageSize, enableCompression, followRedirects, identity)
-
- def forLocator(
- locator: ServiceLocator,
- name: String,
- userAgent: String = RestClient.DefaultUserAgent,
- idleTimeout: Duration = 5.minutes,
- connectTimeout: Duration = 5.seconds,
- maxMessageSize: Int = 8912,
- enableCompression: Boolean = true,
- followRedirects: Boolean = true,
- identity: String = "0"): SwaggerConfig =
- new DefaultSwaggerConfig(locator, userAgent, idleTimeout, connectTimeout, maxMessageSize, enableCompression, followRedirects, identity, name)
- }
-
- case class ContentType(name: String, headerValue: String)
- trait SwaggerConfig {
- def locator: ServiceLocator
- def userAgent: String
- def idleTimeout: Duration
- def connectTimeout: Duration
- def maxMessageSize: Int
- def enableCompression: Boolean
- def followRedirects: Boolean
- def identity: String
- def name: String
- def contentType: ContentType
- }
-
-
diff --git a/src/main/scala_2.11/io/swagger/client/TransportClient.scala b/src/main/scala_2.11/io/swagger/client/TransportClient.scala
deleted file mode 100644
index 7d65c2e..0000000
--- a/src/main/scala_2.11/io/swagger/client/TransportClient.scala
+++ /dev/null
@@ -1,107 +0,0 @@
-package io.swagger.client
-
-import com.ning.http._
-import client._
-import scala.concurrent.{Promise, ExecutionContext, Future}
-import scala.concurrent.duration._
-import java.net.URI
-import org.json4s._
-import scala.util.Try
-import scala.annotation.implicitNotFound
-
-
-trait ClientResponse {
- def cookies: Map[String, RestClient.Cookie]
- def headers: Map[String, Seq[String]]
- def status: ResponseStatus
- def contentType: String
- def mediaType: Option[String]
- def charset: Option[String]
- def uri: URI
- def statusCode: Int = status.code
- def statusText: String = status.line
- def body: String
-}
-
-@implicitNotFound(
- "No ClientResponseReader found for type ${T}. Try to implement an implicit ClientResponseReader for this type, or perhaps you're just missing an import like ClientResponseReader._."
-)
-trait ClientResponseReader[T] {
- def read(resp: ClientResponse): T
-}
-
-object ClientResponseReaders {
-
- private def rdr[T](fn: ClientResponse => T): ClientResponseReader[T] = new ClientResponseReader[T] {
- def read(resp: ClientResponse): T = fn(resp)
- }
-
- implicit val StringReader: ClientResponseReader[String] = rdr(_.body)
- implicit val JValueReader: ClientResponseReader[JValue] = rdr(r => jackson.parseJson(r.body))
- implicit val UnitReader: ClientResponseReader[Unit] = rdr(_ => ())
- implicit def OptionReader[T](implicit reader: ClientResponseReader[T]): ClientResponseReader[Option[T]] = rdr { resp =>
- try {
- if (resp.statusCode / 100 == 2) Option(reader.read(resp)) else None
- } catch {
- case _: Throwable => None
- }
- }
- implicit def TryReader[T](implicit reader: ClientResponseReader[T]): ClientResponseReader[Try[T]] =
- rdr { resp =>
- try {
- if (resp.statusCode / 100 == 2) Try(reader.read(resp))
- else scala.util.Failure(new ApiException(resp))
- } catch {
- case t: Throwable => scala.util.Failure(t)
- }
- }
-
-
- object JsonTypeClassReader {
- implicit def JsonFormatsReader[T](implicit jsonReader: org.json4s.Reader[T]): ClientResponseReader[T] =
- rdr(resp => jsonReader.read(JValueReader.read(resp)))
- }
-
- object Json4sFormatsReader {
- implicit def JsonFormatsReader[T](implicit formats: org.json4s.Formats, mf: Manifest[T]): ClientResponseReader[T] =
- rdr(resp => jackson.parseJson(resp.body).extract[T])
- }
-
-}
-
-@implicitNotFound(
- "No RequestWriter found for type ${T}. Try to implement an implicit RequestWriter for this type, or perhaps you're just missing an import like RequestWriters._."
-)
-trait RequestWriter[T] {
- def write(body: T): String
-}
-object RequestWriters {
- private def wrtr[T](fn: T => String) = new RequestWriter[T] {
- def write(body: T): String = fn(body)
- }
-
- implicit val StringWriter: RequestWriter[String] = wrtr(identity)
- implicit val JValueWriter: RequestWriter[JValue] = wrtr(jackson.compactJson)
- implicit def OptionWriter[T](implicit writer: RequestWriter[T]): RequestWriter[Option[T]] =
- wrtr(o => o map writer.write getOrElse "")
-
- object JsonTypeClassWriter {
- implicit def JsonFormatsWriter[T](implicit jsonWriter: org.json4s.Writer[T]): RequestWriter[T] =
- wrtr(bd => JValueWriter write jsonWriter.write(bd))
- }
-
- object Json4sFormatsWriter {
- implicit def JsonFormatsWriter[T](implicit formats: Formats, mf: Manifest[T]): RequestWriter[T] =
- wrtr(bd => JValueWriter write Extraction.decompose(bd))
- }
-}
-
-trait TransportClient {
- protected def locator: ServiceLocator
- protected def clientConfig: AsyncHttpClientConfig
- protected def createClient(): AsyncHttpClient
- implicit def execContext: ExecutionContext
- def open(): Future[Unit] = Promise.successful(()).future
- def submit(method: String, uri: String, params: Iterable[(String, Any)], headers: Iterable[(String, String)], body: String, timeout: Duration = 90.seconds): Future[ClientResponse]
- def close(): Unit
-}
diff --git a/src/main/scala_2.9/io/swagger/client/ApiClient.scala b/src/main/scala_2.9/io/swagger/client/ApiClient.scala
deleted file mode 100644
index 783166d..0000000
--- a/src/main/scala_2.9/io/swagger/client/ApiClient.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.swagger.client
-
-import akka.dispatch.{Future, Promise}
-import org.json4s.jackson.JsonMethods
-
-abstract class ApiClient(client: TransportClient, config: SwaggerConfig) extends JsonMethods {
- protected implicit val execContext = client.execContext
- protected val ser = config.dataFormat
-
- protected def addFmt(pth: String) = pth.replace("{format}", ser.name)
-
- protected def process[T](fn: => T): Future[T] = {
- val fut = Promise[T]
- try {
- val r = fn
- r match {
- case t: Throwable => fut.complete(Left(t))
- case s => fut.complete(Right(r))
- }
- } catch {
- case t: Throwable => fut.complete(Left(t))
- }
- fut
- }
-}
diff --git a/src/main/scala_2.9/io/swagger/client/Logging.scala b/src/main/scala_2.9/io/swagger/client/Logging.scala
deleted file mode 100644
index d9cafcd..0000000
--- a/src/main/scala_2.9/io/swagger/client/Logging.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package io.swagger.client
-
-import grizzled.slf4j.Logger
-
-trait Logging {
- @transient lazy val logger: Logger = Logger(getClass)
-}
\ No newline at end of file
diff --git a/src/main/scala_2.9/io/swagger/client/RestClient.scala b/src/main/scala_2.9/io/swagger/client/RestClient.scala
deleted file mode 100644
index 3bd8c40..0000000
--- a/src/main/scala_2.9/io/swagger/client/RestClient.scala
+++ /dev/null
@@ -1,456 +0,0 @@
-package io.swagger.client
-
-import com.ning.http._
-import client._
-import client.{ Cookie => AhcCookie }
-import collection.JavaConverters._
-import java.util.{TimeZone, Date, Locale}
-import java.util.concurrent.ConcurrentHashMap
-import io.Codec
-import java.nio.charset.Charset
-import java.io.File
-import java.net.URI
-import rl.MapQueryString
-import akka.dispatch.{Promise, ExecutionContext, Future}
-import akka.util.Duration
-import akka.util.duration._
-import org.json4s._
-import org.json4s.jackson.JsonMethods
-import java.text.SimpleDateFormat
-import io.swagger.client.async.BuildInfo
-import java.util.concurrent.atomic.AtomicLong
-import java.util.{ concurrent => juc }
-import org.jboss.netty.util.{HashedWheelTimer, Timer}
-import org.jboss.netty.channel.socket.nio.{NioWorkerPool, NioClientSocketChannelFactory}
-import com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig
-
-
-object RestClient {
- private val threadIds = new AtomicLong()
-
- private lazy val factory = new juc.ThreadFactory {
- def newThread(runnable: Runnable): Thread = {
- val thread = new Thread(runnable)
- thread.setName("bragi-client-thread-" + threadIds.incrementAndGet())
- thread.setDaemon(true)
- thread
- }
- }
-
- val DefaultUserAgent = "Reverb SwaggerClient / " + BuildInfo.version
-
- private implicit def stringWithExt(s: String) = new {
- def isBlank = s == null || s.trim.isEmpty
- def nonBlank = !isBlank
- def blankOption = if (isBlank) None else Option(s)
- }
-
- case class CookieOptions( domain : String = "",
- path : String = "",
- maxAge : Int = -1,
- secure : Boolean = false,
- comment : String = "",
- httpOnly: Boolean = false,
- version : Int = 0,
- encoding: String = "UTF-8")
-
- trait HttpCookie {
- implicit def cookieOptions: CookieOptions
- def name: String
- def value: String
-
- }
-
- case class RequestCookie(name: String, value: String, cookieOptions: CookieOptions = CookieOptions()) extends HttpCookie
- object DateUtil {
- @volatile private[this] var _currentTimeMillis: Option[Long] = None
- def currentTimeMillis = _currentTimeMillis getOrElse System.currentTimeMillis
- def currentTimeMillis_=(ct: Long) = _currentTimeMillis = Some(ct)
- def freezeTime() = _currentTimeMillis = Some(System.currentTimeMillis())
- def unfreezeTime() = _currentTimeMillis = None
- def formatDate(date: Date, format: String, timeZone: TimeZone = TimeZone.getTimeZone("GMT")) = {
- val df = new SimpleDateFormat(format)
- df.setTimeZone(timeZone)
- df.format(date)
- }
- }
-
-
- case class Cookie(name: String, value: String)(implicit val cookieOptions: CookieOptions = CookieOptions()) extends HttpCookie {
-
- private def ensureDotDomain =
- (if (!cookieOptions.domain.startsWith(".")) "." + cookieOptions.domain else cookieOptions.domain).toLowerCase(Locale.ENGLISH)
-
- def toCookieString = {
- val sb = new StringBuffer
- sb append name append "="
- sb append value
-
- if(cookieOptions.domain.nonBlank && cookieOptions.domain != "localhost")
- sb.append("; Domain=").append(ensureDotDomain)
-
- val pth = cookieOptions.path
- if(pth.nonBlank) sb append "; Path=" append (if(!pth.startsWith("/")) {
- "/" + pth
- } else { pth })
-
- if(cookieOptions.comment.nonBlank) sb append ("; Comment=") append cookieOptions.comment
-
- appendMaxAge(sb, cookieOptions.maxAge, cookieOptions.version)
-
- if (cookieOptions.secure) sb append "; Secure"
- if (cookieOptions.httpOnly) sb append "; HttpOnly"
- sb.toString
- }
- private[this] def appendMaxAge(sb: StringBuffer, maxAge: Int, version: Int) = {
- val dateInMillis = maxAge match {
- case a if a < 0 => None // we don't do anything for max-age when it's < 0 then it becomes a session cookie
- case 0 => Some(0L) // Set the date to the min date for the system
- case a => Some(DateUtil.currentTimeMillis + a * 1000)
- }
-
- // This used to be Max-Age but IE is not always very happy with that
- // see: http://mrcoles.com/blog/cookies-max-age-vs-expires/
- // see Q1: http://blogs.msdn.com/b/ieinternals/archive/2009/08/20/wininet-ie-cookie-internals-faq.aspx
- val bOpt = dateInMillis map (ms => appendExpires(sb, new Date(ms)))
- val agedOpt = if (version > 0) bOpt map (_.append("; Max-Age=").append(maxAge)) else bOpt
- agedOpt getOrElse sb
- }
-
- private[this] def appendExpires(sb: StringBuffer, expires: Date) =
- sb append "; Expires=" append formatExpires(expires)
-
- private[this] def formatExpires(date: Date) = DateUtil.formatDate(date, "EEE, dd MMM yyyy HH:mm:ss zzz")
-
- }
-
-
- class CookieJar(private val reqCookies: Map[String, RequestCookie]) {
- private val cookies = new ConcurrentHashMap[String, HttpCookie].asScala ++ reqCookies
-
- def get(key: String) = cookies.get(key) filter (_.cookieOptions.maxAge != 0) map (_.value)
-
- def apply(key: String) = get(key) getOrElse (throw new Exception("No cookie could be found for the specified key [%s]" format key))
-
- def update(name: String, value: String)(implicit cookieOptions: CookieOptions=CookieOptions()) = {
- cookies += name -> Cookie(name, value)(cookieOptions)
- }
-
- def set(name: String, value: String)(implicit cookieOptions: CookieOptions=CookieOptions()) = {
- this.update(name, value)(cookieOptions)
- }
-
- def delete(name: String)(implicit cookieOptions: CookieOptions = CookieOptions(maxAge = 0)) {
- this.update(name, "")(cookieOptions.copy(maxAge = 0))
- }
-
- def +=(keyValuePair: (String, String))(implicit cookieOptions: CookieOptions = CookieOptions()) = {
- this.update(keyValuePair._1, keyValuePair._2)(cookieOptions)
- }
-
- def -=(key: String)(implicit cookieOptions: CookieOptions = CookieOptions(maxAge = 0)) {
- delete(key)(cookieOptions)
- }
-
- def size = cookies.size
-
- def foreach[U](fn: (HttpCookie) => U) = cookies foreach { case (_, v) => fn(v) }
-
- private[client] def responseCookies = cookies.values collect { case c: Cookie => c }
-
- override def toString: String = cookies.toString()
- }
-
-
- class RestClientResponse(response: Response) extends ClientResponse {
- val cookies = (response.getCookies.asScala map { cookie =>
- val cko = CookieOptions(cookie.getDomain, cookie.getPath, cookie.getMaxAge)
- cookie.getName -> Cookie(cookie.getName, cookie.getValue)(cko)
- }).toMap
-
- val headers = (response.getHeaders.keySet().asScala map { k => k -> response.getHeaders(k).asScala.toSeq}).toMap
-
- val status = ResponseStatus(response.getStatusCode, response.getStatusText)
-
- val contentType = response.getContentType
-
- val inputStream = response.getResponseBodyAsStream
-
- val uri = response.getUri
-
- def body = response.getResponseBody(charset getOrElse "UTF-8")
-
- def mediaType: Option[String] = headers.get("Content-Type") flatMap { _.headOption }
-
- def charset: Option[String] =
- for {
- ct <- mediaType
- charset <- ct.split(";").drop(1).headOption
- } yield charset.toUpperCase.replace("CHARSET=", "").trim
- }
-
- trait Defaults {
- def builder: AsyncHttpClientConfig.Builder
- def timer: Timer
- }
-
- private object InternalDefaults {
- /** true if we think we're runing un-forked in an sbt-interactive session */
- val inTrapExit = (
- for (group ← Option(Thread.currentThread.getThreadGroup))
- yield group.getName == "trap.exit").getOrElse(false)
-
- /** Sets a user agent, no timeout for requests */
- object BasicDefaults extends Defaults {
- lazy val timer = new HashedWheelTimer()
- def builder = (new AsyncHttpClientConfig.Builder()
- setAllowPoolingConnection true
- setRequestTimeoutInMs 45000
- setCompressionEnabled true
- setFollowRedirects false
- setMaximumConnectionsPerHost 200
- setUserAgent DefaultUserAgent
- setMaxRequestRetry 0)
- }
-
- /** Uses daemon threads and tries to exit cleanly when running in sbt */
- object SbtProcessDefaults extends Defaults {
- def builder = {
- val shuttingDown = new juc.atomic.AtomicBoolean(false)
- /** daemon threads that also shut down everything when interrupted! */
- lazy val interruptThreadFactory = new juc.ThreadFactory {
- def newThread(runnable: Runnable) = {
- new Thread(runnable) {
- setDaemon(true)
- setName("bragi-client-thread-" + threadIds.incrementAndGet())
- override def interrupt() {
- shutdown()
- super.interrupt()
- }
- }
- }
- }
- lazy val nioClientSocketChannelFactory = {
- val workerCount = 2 * Runtime.getRuntime().availableProcessors()
- new NioClientSocketChannelFactory(
- juc.Executors.newCachedThreadPool(interruptThreadFactory),
- 1,
- new NioWorkerPool(
- juc.Executors.newCachedThreadPool(interruptThreadFactory),
- workerCount),
- timer)
- }
-
- def shutdown() {
- if (shuttingDown.compareAndSet(false, true)) {
- nioClientSocketChannelFactory.releaseExternalResources()
- }
- }
-
- BasicDefaults.builder.setAsyncHttpClientProviderConfig(
- new NettyAsyncHttpProviderConfig().addProperty(
- NettyAsyncHttpProviderConfig.SOCKET_CHANNEL_FACTORY,
- nioClientSocketChannelFactory))
- }
- lazy val timer = new HashedWheelTimer(factory)
- }
- }
-}
-
-class RestClient(config: SwaggerConfig) extends TransportClient with Logging {
- import RestClient._
- protected def underlying: Defaults = {
- if (InternalDefaults.inTrapExit) InternalDefaults.SbtProcessDefaults
- else InternalDefaults.BasicDefaults
- }
- protected val locator: ServiceLocator = config.locator
- protected val clientConfig: AsyncHttpClientConfig = (underlying.builder
- setUserAgent config.userAgent
- setRequestTimeoutInMs config.idleTimeout.toMillis.toInt
- setConnectionTimeoutInMs config.connectTimeout.toMillis.toInt
- setCompressionEnabled config.enableCompression // enable content-compression
- setAllowPoolingConnection true // enable http keep-alive
- setFollowRedirects config.followRedirects).build()
-
- import StringHttpMethod._
- implicit val execContext = ExecutionContext.fromExecutorService(clientConfig.executorService())
-
- private[this] val mimes = new Mimes {
- protected def warn(message: String) = logger.warn(message)
- }
-
- private[this] val cookies = new CookieJar(Map.empty)
-
- protected def createClient() = new AsyncHttpClient(clientConfig) {
- def preparePatch(uri: String): AsyncHttpClient#BoundRequestBuilder = requestBuilder(PATCH, uri)
- def prepareTrace(uri: String): AsyncHttpClient#BoundRequestBuilder = requestBuilder(TRACE, uri)
- }
-
- private[this] val client = createClient()
-
- private[this] def createRequest(method: String): String ⇒ AsyncHttpClient#BoundRequestBuilder = {
- method.toUpperCase(Locale.ENGLISH) match {
- case `GET` ⇒ client.prepareGet _
- case `POST` ⇒ client.preparePost _
- case `PUT` ⇒ client.preparePut _
- case `DELETE` ⇒ client.prepareDelete _
- case `HEAD` ⇒ client.prepareHead _
- case `OPTIONS` ⇒ client.prepareOptions _
- case `CONNECT` ⇒ client.prepareConnect _
- case `PATCH` ⇒ client.preparePatch _
- case `TRACE` ⇒ client.prepareTrace _
- }
- }
-
- private[this] def addTimeout(timeout: Duration)(req: AsyncHttpClient#BoundRequestBuilder) = {
- if (timeout.isFinite()) {
- val prc = new PerRequestConfig()
- prc.setRequestTimeoutInMs(timeout.toMillis.toInt)
- req.setPerRequestConfig(prc)
- }
- req
- }
-
- private[this] def addParameters(method: String, params: Iterable[(String, String)], isMultipart: Boolean = false, charset: Charset = Codec.UTF8)(req: AsyncHttpClient#BoundRequestBuilder) = {
- method.toUpperCase(Locale.ENGLISH) match {
- case `GET` | `DELETE` | `HEAD` | `OPTIONS` ⇒ params foreach { case (k, v) ⇒ req addQueryParameter (k, v) }
- case `PUT` | `POST` | `PATCH` ⇒ {
- if (!isMultipart)
- if (req.build().getHeaders.getFirstValue("Content-Type").startsWith("application/x-www-form-urlencoded"))
- params foreach { case (k, v) ⇒ req addParameter (k, v) }
- else
- params foreach { case (k, v) => req addQueryParameter(k, v) }
- else {
- params foreach { case (k, v) => req addBodyPart new StringPart(k, v, charset.name)}
- }
- }
- case _ ⇒ // we don't care, carry on
- }
- req
- }
-
- private[this] def addHeaders(headers: Iterable[(String, String)], files: Iterable[(String, File)])(req: AsyncHttpClient#BoundRequestBuilder) = {
- headers foreach { case (k, v) => req.addHeader(k, v) }
- if (!Map(headers.map(kv => kv._1.toUpperCase -> kv._2).toSeq:_*).contains("CONTENT-TYPE"))
- req.setHeader("Content-Type", defaultWriteContentType(files)("Content-Type"))
- req
- }
-
- private[this] def addFiles(files: Iterable[(String, File)], isMultipart: Boolean)(req: AsyncHttpClient#BoundRequestBuilder) = {
- if (isMultipart) {
- files foreach { case (nm, file) =>
- req.addBodyPart(new FilePart(nm, file, mimes(file), FileCharset(file).name))
- }
- }
- req
- }
-
- private[this] def addCookies(req: AsyncHttpClient#BoundRequestBuilder) = {
- cookies foreach { cookie =>
- val ahcCookie = new AhcCookie(
- cookie.cookieOptions.domain,
- cookie.name,
- cookie.value,
- cookie.cookieOptions.path,
- cookie.cookieOptions.maxAge,
- cookie.cookieOptions.secure,
- cookie.cookieOptions.version)
- req.addCookie(ahcCookie)
- }
- req
- }
-
- private[this] def addQuery(u: URI)(req: AsyncHttpClient#BoundRequestBuilder) = {
- u.getQuery.blankOption foreach { uu =>
- rl.QueryString(uu) match {
- case m: MapQueryString => m.value foreach { case (k, v) => v foreach { req.addQueryParameter(k, _) } }
- case _ =>
- }
- }
- req
- }
-
- private[this] val allowsBody = Vector(PUT, POST, PATCH)
-
-
- private[this] def addBody(method: String, body: String)(req: AsyncHttpClient#BoundRequestBuilder) = {
- if (allowsBody.contains(method.toUpperCase(Locale.ENGLISH)) && body.nonBlank) {
- req.setBody(body)
- }
- req
- }
-
-
- private[this] def requestFiles(params: Iterable[(String, Any)]) = params collect { case (k, v: File) => k -> v }
- private[this] def paramsFrom(params: Iterable[(String, Any)]) = params collect {
- case (k, v: String) => k -> v
- case (k, null) => k -> ""
- case (k, v) => k -> v.toString
- }
- private[this] def isMultipartRequest(method: String, headers: Iterable[(String, String)], files: Iterable[(String, File)]) = {
- allowsBody.contains(method.toUpperCase(Locale.ENGLISH)) && {
- val ct = (defaultWriteContentType(files) ++ headers)("Content-Type")
- ct.toLowerCase(Locale.ENGLISH).startsWith("multipart/form-data")
- }
- }
-
- private[this] def requestUri(base: URI, u: URI) = if (u.isAbsolute) u else {
- // There is no constructor on java.net.URI that will not encode the path
- // except for the one where you pass in a uri as string so we're concatenating ourselves
- val prt = base.getPort
- val b =
- if (prt > 0 && prt != 80 && prt != 443) "%s://%s:%d".format(base.getScheme, base.getHost, prt)
- else "%s://%s".format(base.getScheme, base.getHost)
- val p = base.getRawPath + u.getRawPath.blankOption.getOrElse("/")
- val q = u.getRawQuery.blankOption.map("?"+_).getOrElse("")
- val f = u.getRawFragment.blankOption.map("#"+_).getOrElse("")
- URI.create(b+p+q+f)
- }
-
- def submit(method: String, uri: String, params: Iterable[(String, Any)], headers: Iterable[(String, String)], body: String = "", timeout: Duration = 90.seconds): Future[RestClientResponse] = {
- val u = URI.create(uri).normalize()
- val files = requestFiles(params)
- val isMultipart = isMultipartRequest(method, headers, files)
-
- locator.pickOneAsUri(config.name, "") flatMap { opt =>
- if (opt.isEmpty) sys.error("No host could be found for %s".format(config.name))
- else {
- val baseUrl = opt.get
- (createRequest(method)
- andThen addTimeout(timeout)
- andThen addHeaders(headers, files)
- andThen addCookies
- andThen addParameters(method, paramsFrom(params), isMultipart)
- andThen addQuery(u)
- andThen addBody(method, body)
- andThen addFiles(files, isMultipart)
- andThen executeRequest)(requestUri(URI.create(baseUrl).normalize(), u).toASCIIString)
- }
- }
- }
-
- private[this] def executeRequest(req: AsyncHttpClient#BoundRequestBuilder) = {
- logger.debug("Requesting:\n" + req.build())
- val promise = Promise[RestClientResponse]()
- req.execute(new AsyncCompletionHandler[Future[ClientResponse]] {
- override def onThrowable(t: Throwable) = promise.complete(Left(t))
- def onCompleted(response: Response) = {
- logger.debug("Got response ["+response.getStatusCode+" "+response.getStatusText+"] for request to "+req.build().getUrl+".\n"+response)
- if (response.getStatusCode / 100 == 2)
- promise.complete(Right(new RestClientResponse(response)))
- else {
- promise.complete(Left(new ApiException(response.getStatusCode, response.getStatusText, response.getResponseBody(Codec.UTF8.name()))))
- }
- }
- })
- promise
- }
-
- private[this] def defaultWriteContentType(files: Iterable[(String, File)]) = {
- val value = if (files.nonEmpty) "multipart/form-data" else config.dataFormat.contentType
- Map("Content-Type" -> value)
- }
-
- def close() = Future { client.close() }
-}
-
diff --git a/src/main/scala_2.9/io/swagger/client/ServiceLocator.scala b/src/main/scala_2.9/io/swagger/client/ServiceLocator.scala
deleted file mode 100644
index 5e93184..0000000
--- a/src/main/scala_2.9/io/swagger/client/ServiceLocator.scala
+++ /dev/null
@@ -1,78 +0,0 @@
-package io.swagger.client
-
-import akka.dispatch.{Promise, Await, Future, ExecutionContext}
-import akka.util.duration._
-import akka.util.FiniteDuration
-import java.net.URI
-import java.util.concurrent.Executors
-
-/**
- * A trait for a load balancing strategy.
- * It takes a set of hosts and returns a single host
- * from the Set
- */
-trait HostPicker {
- /**
- * Pick a host from the provided list of services
- * @param hosts The hosts to pick from
- * @return A Future with an Option that contains the host if there was one.
- */
- def apply(hosts: Set[String])(implicit executionContext: ExecutionContext): Future[Option[String]]
-}
-
-object HeadHostPicker extends HostPicker {
- def apply(hosts: Set[String])(implicit executionContext: ExecutionContext): Future[Option[String]] = {
- Future(hosts.headOption)
- }
-}
-
-object RandomHostPicker extends HostPicker {
- private[this] val rand = new util.Random()
- def apply(hosts: Set[String])(implicit executionContext: ExecutionContext): Future[Option[String]] = {
- Future(if (hosts.nonEmpty) Some(hosts.toList(rand.nextInt(hosts.size))) else None)
- }
-}
-
-trait ServiceLocator {
- implicit protected def executionContext: ExecutionContext
- def locate(name: String): Future[Set[String]]
- def locateBlocking(name: String, atMost: FiniteDuration = 20 seconds): Set[String] =
- Await.result(locate(name), atMost)
-
- def pickOne(name: String, picker: HostPicker = RandomHostPicker): Future[Option[String]]
-
- def pickOneBlocking(name: String, picker: HostPicker = RandomHostPicker, atMost: FiniteDuration = 20 seconds): Option[String] =
- Await.result(pickOne(name, picker), atMost)
-
- def locateAsUris(name: String, path: String): Future[Set[String]]
- def locateAsUrisBlocking(name: String, path: String, atMost: FiniteDuration = 20 seconds): Set[String] =
- Await.result(locateAsUris(name, path), atMost)
-
- def pickOneAsUri(name: String, path: String, picker: HostPicker = RandomHostPicker): Future[Option[String]]
-
- def pickOneAsUriBlocking(name: String, path: String, picker: HostPicker = RandomHostPicker, atMost: FiniteDuration = 20 seconds): Option[String] =
- Await.result(pickOneAsUri(name, path, picker), atMost)
-
-}
-
-object GlobalContext {
- lazy val executionContext: ExecutionContext = ExecutionContext.fromExecutor(Executors.newCachedThreadPool())
-
-}
-
-case class BaseUrl(url: String)(implicit protected val executionContext: ExecutionContext = GlobalContext.executionContext) extends ServiceLocator {
- private[this] val uri = URI.create(url)
- private[this] val withoutScheme = uri.getHost
- private[this] val withScheme = uri.getScheme + "://" + uri.getAuthority + stripTrailingSlash(uri.getPath)
-
-
- def locate(name: String): Future[Set[String]] = Promise.successful(Set(withoutScheme)).future
-
- def pickOne(name: String, picker: HostPicker): Future[Option[String]] = Promise.successful(Some(withoutScheme)).future
-
- def locateAsUris(name: String, path: String): Future[Set[String]] = Promise.successful(Set(withScheme)).future
-
- def pickOneAsUri(name: String, path: String, picker: HostPicker): Future[Option[String]] = Promise.successful(Some(withScheme)).future
-
- private[this] def stripTrailingSlash(s: String): String = if (s endsWith "/") s.dropRight(1) else s
-}
diff --git a/src/main/scala_2.9/io/swagger/client/SwaggerConfig.scala b/src/main/scala_2.9/io/swagger/client/SwaggerConfig.scala
deleted file mode 100644
index 164b7af..0000000
--- a/src/main/scala_2.9/io/swagger/client/SwaggerConfig.scala
+++ /dev/null
@@ -1,108 +0,0 @@
-package io.swagger.client
-
-import akka.util.Duration
-import akka.util.duration._
-import java.io.StringWriter
-import org.json4s.jackson.JsonMethods
-import SwaggerConfig.DataFormat
-import org.json4s._
-import org.json4s.Xml._
-import io.Codec
-
-object SwaggerConfig {
- sealed trait DataFormat {
-
- def name: String
- def contentType: String
-
- def serialize[T](obj: T): String
- def deserialize[T:Manifest](json: String): T
- }
- object DataFormat {
- object Json {
- def apply(fmts: Formats) = new Json(fmts)
- }
- class Json(fmts: Formats) extends DataFormat {
- implicit protected val jsonFormats: Formats = fmts
- val contentType: String = "application/json;charset=utf-8"
- val name: String = "json"
- def deserialize[T: Manifest](json: String): T = JsonMethods.parse(json, fmts.wantsBigDecimal).extract[T]
- def serialize[T](obj: T): String = JsonMethods.compact(JsonMethods.render(Extraction.decompose(obj)))
- }
-
- object XML {
- def apply(fmts: Formats) = new XML(fmts)
- }
- class XML(fmts: Formats) extends DataFormat {
- implicit protected val jsonFormats: Formats = fmts
- val contentType: String = "application/xml"
-
- val name: String = "xml"
-
- def deserialize[T: Manifest](json: String): T = {
- val JObject(JField(_, jv) :: Nil) = toJson(scala.xml.XML.loadString(json))
- jv.extract[T]
- }
-
- protected lazy val xmlRootNode =
-
- def serialize[T](obj: T): String = {
- val json = Extraction.decompose(obj)
- val sw = new StringWriter()
- scala.xml.XML.write(sw, xmlRootNode.copy(child = toXml(json)), Codec.UTF8.name, true, null)
- sw.toString
- }
- }
- }
-
- private case class DefaultSwaggerConfig(
- locator: ServiceLocator,
- override val userAgent: String = RestClient.DefaultUserAgent,
- override val dataFormat: SwaggerConfig.DataFormat = DataFormat.Json(DefaultFormats),
- override val idleTimeout: Duration = 5.minutes,
- override val connectTimeout: Duration = 5.seconds,
- override val maxMessageSize: Int = 8912,
- override val enableCompression: Boolean = true,
- override val followRedirects: Boolean = true,
- override val identity: String = "0",
- override val name: String = "no-name") extends SwaggerConfig
-
- def forUrl(
- baseUrl: String,
- userAgent: String = RestClient.DefaultUserAgent,
- dataFormat: SwaggerConfig.DataFormat = DataFormat.Json(DefaultFormats),
- idleTimeout: Duration = 5.minutes,
- connectTimeout: Duration = 5.seconds,
- maxMessageSize: Int = 8912,
- enableCompression: Boolean = true,
- followRedirects: Boolean = true,
- identity: String = "0"): SwaggerConfig =
- new DefaultSwaggerConfig(BaseUrl(baseUrl), userAgent, dataFormat, idleTimeout, connectTimeout, maxMessageSize, enableCompression, followRedirects, identity)
-
- def forLocator(
- locator: ServiceLocator,
- name: String,
- userAgent: String = RestClient.DefaultUserAgent,
- dataFormat: SwaggerConfig.DataFormat = DataFormat.Json(DefaultFormats),
- idleTimeout: Duration = 5.minutes,
- connectTimeout: Duration = 5.seconds,
- maxMessageSize: Int = 8912,
- enableCompression: Boolean = true,
- followRedirects: Boolean = true,
- identity: String = "0"): SwaggerConfig =
- new DefaultSwaggerConfig(locator, userAgent, dataFormat, idleTimeout, connectTimeout, maxMessageSize, enableCompression, followRedirects, identity, name)
-}
-
-trait SwaggerConfig {
- def locator: ServiceLocator
- def userAgent: String = RestClient.DefaultUserAgent
- def dataFormat: SwaggerConfig.DataFormat = DataFormat.Json(DefaultFormats)
- def idleTimeout: Duration = 5.minutes
- def connectTimeout: Duration = 5.seconds
- def maxMessageSize: Int = 8912
- def enableCompression: Boolean = true
- def followRedirects: Boolean = true
- def identity: String = "0"
- def name: String = "no-name"
-}
-
diff --git a/src/main/scala_2.9/io/swagger/client/TransportClient.scala b/src/main/scala_2.9/io/swagger/client/TransportClient.scala
deleted file mode 100644
index 999e144..0000000
--- a/src/main/scala_2.9/io/swagger/client/TransportClient.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package io.swagger.client
-
-import com.ning.http._
-import client._
-import akka.dispatch.{Promise, ExecutionContext, Future}
-import akka.util.Duration
-import akka.util.duration._
-import java.net.URI
-import org.json4s._
-
-
-trait ClientResponse {
- def cookies: Map[String, RestClient.Cookie]
- def headers: Map[String, Seq[String]]
- def status: ResponseStatus
- def contentType: String
- def mediaType: Option[String]
- def charset: Option[String]
- def uri: URI
- def statusCode: Int = status.code
- def statusText: String = status.line
- def body: String
-
-}
-
-trait TransportClient {
- protected def locator: ServiceLocator
- protected def clientConfig: AsyncHttpClientConfig
- implicit def execContext: ExecutionContext
- def open(): Future[Unit] = Promise.successful(()).future
- def submit(method: String, uri: String, params: Iterable[(String, Any)], headers: Iterable[(String, String)], body: String, timeout: Duration = 90.seconds): Future[ClientResponse]
- def close(): Future[Unit]
-}