Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX #82 adding the ability to specify jvm options via sbt #510

Merged
merged 1 commit into from
Mar 28, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=0.13.6
sbt.version=0.13.8
6 changes: 3 additions & 3 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ resolvers += Resolver.url("sbt-plugin-releases", new URL("http://scalasbt.artifa

resolvers += "jgit-repo" at "http://download.eclipse.org/jgit/maven"

addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.5.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.5.3")

addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.6.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.8.0")

addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "0.7.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "0.8.1")

libraryDependencies <+= (sbtVersion) { sv =>
"org.scala-sbt" % "scripted-plugin" % sv
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# #################################
# ##### Default configuration #####
# #################################

# Available replacements
# ------------------------------------------------
# ${{author}} debian author
# ${{descr}} debian package description
# ${{exec}} startup script name
# ${{chdir}} app directory
# ${{retries}} retries for startup
# ${{retryTimeout}} retry timeout
# ${{app_name}} normalized app name
# ${{daemon_user}} daemon user
# -------------------------------------------------

# DEPRECATED, use -J-Xmx1024m instead
# -mem 1024

# Setting -X directly (-J is stripped)
# -J-X
# -J-Xmx1024

# Add additional jvm parameters
# -Dkey=val

# For play applications you may set
# -Dpidfile.path=/var/run/${{app_name}}/play.pid

# Turn on JVM debugging, open at the given port
# -jvm-debug <port>

# Don't run the java version check
# -no-version-check
Original file line number Diff line number Diff line change
Expand Up @@ -150,34 +150,7 @@ addResidual () {
addDebugger () {
addJava "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$1"
}
# a ham-fisted attempt to move some memory settings in concert
# so they need not be messed around with individually.
get_mem_opts () {
local mem=${1:-1024}
local perm=$(( $mem / 4 ))
(( $perm > 256 )) || perm=256
(( $perm < 1024 )) || perm=1024
local codecache=$(( $perm / 2 ))

# if we detect any of these settings in ${java_opts} we need to NOT output our settings.
# The reason is the Xms/Xmx, if they don't line up, cause errors.
if [[ "${java_opts}" == *-Xmx* ]] ||
[[ "${java_opts}" == *-Xms* ]] ||
[[ "${java_opts}" == *-XX:MaxPermSize* ]] ||
[[ "${java_opts}" == *-XX:ReservedCodeCacheSize* ]] ||
# check java arguments for settings, too
[[ "${java_args[@]}" == *-Xmx* ]] ||
[[ "${java_args[@]}" == *-Xms* ]] ||
[[ "${java_args[@]}" == *-XX:MaxPermSize* ]] ||
[[ "${java_args[@]}" == *-XX:ReservedCodeCacheSize* ]];
then
echo ""
elif [[ !$no_version_check ]] && [[ "$java_version" > "1.8" ]]; then
echo "-Xms${mem}m -Xmx${mem}m -XX:ReservedCodeCacheSize=${codecache}m"
else
echo "-Xms${mem}m -Xmx${mem}m -XX:MaxPermSize=${perm}m -XX:ReservedCodeCacheSize=${codecache}m"
fi
}

require_arg () {
local type="$1"
local opt="$2"
Expand Down Expand Up @@ -214,7 +187,7 @@ process_args () {

-no-version-check) no_version_check=1 && shift ;;

-mem) require_arg integer "$1" "$2" && app_mem="$2" && shift 2 ;;
-mem) echo "!! WARNING !! -mem option is ignored. Please use -J-Xmx and -J-Xms" && shift 2 ;;
-jvm-debug) require_arg port "$1" "$2" && addDebugger $2 && shift 2 ;;

-main) custom_mainclass="$2" && shift 2 ;;
Expand Down Expand Up @@ -274,7 +247,6 @@ run() {

# run sbt
execRunner "$java_cmd" \
$(get_mem_opts $app_mem) \
${java_opts[@]} \
"${java_args[@]}" \
-cp "$(fix_classpath "$app_classpath")" \
Expand Down Expand Up @@ -328,7 +300,6 @@ Usage: $script_name [options]
-v | -verbose this runner is chattier
-d | -debug set sbt log level to debug
-no-version-check Don't run the java version check.
-mem <integer> set memory options in MB (default: $sbt_mem, which is $(get_mem_opts $sbt_mem))
-main <classname> Define a custom main class
-jvm-debug <port> Turn on JVM debugging, open at the given port.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# #################################
# ##### Default configuration #####
# #################################
# #####################################
# ##### Environment Configuration #####
# #####################################

# This file gets sourced before the actual bashscript
# gets executed. You can use this file to provide
# environment variables

# Available replacements
# ------------------------------------------------
Expand All @@ -14,21 +18,11 @@
# ${{daemon_user}} daemon user
# -------------------------------------------------

# Setting -Xmx and -Xms in Megabyte
# -mem 1024

# Setting -X directly (-J is stripped)
# -J-X
# -J-Xmx1024

# Add additional jvm parameters
# -Dkey=val

# For play applications you may set
# -Dpidfile.path=/var/run/${{app_name}}/play.pid

# Turn on JVM debugging, open at the given port
# -jvm-debug <port>
# Setting JAVA_OPTS
# -----------------
# JAVA_OPTS="-Dpidfile.path=/var/run/${{app_name}}/play.pid $JAVA_OPTS"

# Don't run the java version check
# -no-version-check
# export env vars for 3rd party libs
# ----------------------------------
# COMPANY_API_KEY=123abc
# export COMPANY_API_KEY
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
source /lib/init/vars.sh
source /lib/lsb/init-functions

# adding bashScriptEnvConfigLocation
[[ -f ${{env_config}} ]] && . ${{env_config}}

# $JAVA_OPTS used in $RUN_CMD wrapper
export JAVA_OPTS

PIDFILE=/var/run/${{app_name}}/running.pid

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
# Source function library.
. /etc/rc.d/init.d/functions

# adding bashScriptEnvConfigLocation
[[ -f ${{env_config}} ]] && . ${{env_config}}

# $JAVA_OPTS used in $RUN_CMD wrapper
export JAVA_OPTS

prog="${{exec}}"

# FIXME The pid file should be handled by the executed script
Expand Down
56 changes: 49 additions & 7 deletions src/main/scala/com/typesafe/sbt/packager/archetypes/JavaApp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package packager
package archetypes

import sbt._
import sbt.Keys.{ mappings, target, name, mainClass, sourceDirectory }
import sbt.Keys.{ mappings, target, name, mainClass, sourceDirectory, javaOptions, streams }
import packager.Keys.{ packageName, executableScriptName }
import linux.{ LinuxFileMetaData, LinuxPackageMapping }
import linux.LinuxPlugin.autoImport.{ linuxPackageMappings, defaultLinuxInstallLocation }
Expand Down Expand Up @@ -39,13 +39,19 @@ object JavaAppPackaging extends AutoPlugin with JavaAppStartScript {
*/
val batTemplate = "bat-template"

/**
* Location for the application.ini file used by the bash script to load initialization parameters for jvm and app
*/
val appIniLocation = "${app_home}/../conf/application.ini"

object autoImport extends JavaAppKeys

import JavaAppPackaging.autoImport._

override def requires = debian.DebianPlugin && rpm.RpmPlugin && docker.DockerPlugin && windows.WindowsPlugin

override def projectSettings = Seq(
javaOptions in Universal := Nil,
// Here we record the classpath as it's added to the mappings separately, so
// we can use its order to generate the bash/bat scripts.
scriptClasspathOrdering := Nil,
Expand All @@ -61,11 +67,34 @@ object JavaAppPackaging extends AutoPlugin with JavaAppStartScript {
mappings in Universal <++= scriptClasspathOrdering,
scriptClasspath <<= scriptClasspathOrdering map makeRelativeClasspathNames,
bashScriptExtraDefines := Nil,
bashScriptConfigLocation <<= bashScriptConfigLocation ?? None,
// Create a bashConfigLocation if options are set in build.sbt
bashScriptConfigLocation <<= bashScriptConfigLocation ?? Some(appIniLocation),
bashScriptEnvConfigLocation <<= bashScriptEnvConfigLocation ?? None,
bashScriptExtraDefines <++= (bashScriptEnvConfigLocation in Universal) map { _.map { config =>
"[[ -f '" + config +"' ]] && source " + config
}.toSeq },
mappings in Universal := {
val log = streams.value.log
val universalMappings = (mappings in Universal).value
val dir = (target in Universal).value
val options = (javaOptions in Universal).value

bashScriptConfigLocation.value.collect {
case location if options.nonEmpty =>
val configFile = dir / "tmp" / "conf" / "application.ini"
IO.writeLines(configFile, "# options from build" +: options)
val filteredMappings = universalMappings.filter {
case (file, path) => path != appIniLocation
}
// Warn the user if he tries to specify options
if (filteredMappings.size < universalMappings.size) {
log.warn("--------!!! JVM Options are defined twice !!!-----------")
log.warn("application.ini is already present in output package. Will be overriden by 'javaOptions in Universal'")
}
(configFile -> cleanApplicationIniPath(location)) +: filteredMappings

}.getOrElse(universalMappings)

},

// ---
bashScriptDefines <<= (Keys.mainClass in (Compile, bashScriptDefines), scriptClasspath in bashScriptDefines, bashScriptExtraDefines, bashScriptConfigLocation) map { (mainClass, cp, extras, config) =>
val hasMain =
for {
Expand Down Expand Up @@ -123,7 +152,7 @@ object JavaAppPackaging extends AutoPlugin with JavaAppStartScript {
artifactClassifier.filterNot(_.isEmpty).map("-" + _).getOrElse("") +
".jar"

// Determines a nicer filename for an attributed jar file, using the
// Determines a nicer filename for an attributed jar file, using the
// ivy metadata if available.
private def getJarFullFilename(dep: Attributed[File]): String = {
val filename: Option[String] = for {
Expand Down Expand Up @@ -208,6 +237,20 @@ object JavaAppPackaging extends AutoPlugin with JavaAppStartScript {
dep <- deps
realDep <- findRealDep(dep, projectArts)
} yield realDep.data -> ("lib/" + getJarFullFilename(realDep))

/**
* Currently unused.
* TODO figure out a proper way to ship default `application.ini` if necessary
*/
protected def applicationIniTemplateSource: java.net.URL = getClass.getResource("application.ini-template")

/**
* @param path that could be relative to app_home
* @return path relative to app_home
*/
private def cleanApplicationIniPath(path: String): String = {
path.replaceFirst("\\$\\{app_home\\}/../", "")
}
}

/**
Expand Down Expand Up @@ -272,4 +315,3 @@ trait JavaAppStartScript {
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ trait JavaAppKeys {
val bashScriptDefines = TaskKey[Seq[String]]("bashScriptDefines", "A list of definitions that should be written to the bash file template.")
val bashScriptExtraDefines = TaskKey[Seq[String]]("bashScriptExtraDefines", "A list of extra definitions that should be written to the bash file template.")
val bashScriptConfigLocation = TaskKey[Option[String]]("bashScriptConfigLocation", "The location where the bash script will load default argument configuration from.")
val bashScriptEnvConfigLocation = TaskKey[Option[String]]("bashScriptEnvConfigLocation", "The location of a bash script that will be sourced before running the app.")
val bashScriptEnvConfigLocation = SettingKey[Option[String]]("bashScriptEnvConfigLocation", "The location of a bash script that will be sourced before running the app.")
val batScriptExtraDefines = TaskKey[Seq[String]]("batScriptExtraDefines", "A list of extra definitions that should be written to the bat file template.")
val scriptClasspathOrdering = TaskKey[Seq[(File, String)]]("scriptClasspathOrdering", "The order of the classpath used at runtime for the bat/bash scripts.")
val projectDependencyArtifacts = TaskKey[Seq[Attributed[File]]]("projectDependencyArtifacts", "The set of exported artifacts from our dependent projects.")
Expand Down
Loading