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

Add a servletSpec setting to choose among runners #988

Merged
merged 5 commits into from
Nov 2, 2024
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 .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ jobs:
- uses: actions/setup-java@v1
with:
java-version: 11
- run: sbt javafmtCheckAll scalafmtCheckAll "scalafixAll --check" test scripted
- run: sbt javafmtCheckAll scalafmtCheckAll "scalafixAll --check" test publishLocal scripted
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ addSbtPlugin("com.earldouglas" % "sbt-war" % "5.0.0-M4")

```scala
scalaVersion := "3.5.1"
libraryDependencies += "jakarta.servlet" % "jakarta.servlet-api" % "6.0.0" % Provided
enablePlugins(SbtWar)
```

Expand Down
70 changes: 66 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,69 @@ ThisBuild / scalacOptions += s"-P:semanticdb:sourceroot:${baseDirectory.value}"
ThisBuild / libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % "test"
ThisBuild / Test / fork := true

lazy val warRunner =
lazy val warRunner_3_0 =
project
.in(file("runner"))
.in(file("runners/3.0"))
.settings(
name := "war-runner",
version := version.value + "_3.0",
Compile / compile / javacOptions ++=
Seq(
"-source",
"11",
"-target",
"11",
"-g:lines"
),
crossPaths := false, // exclude Scala suffix from artifact names
autoScalaLibrary := false, // exclude scala-library from dependencies
libraryDependencies += "com.github.jsimone" % "webapp-runner" % "7.0.91.0"
)

lazy val warRunner_3_1 =
project
.in(file("runners/3.1"))
.settings(
name := "war-runner",
version := version.value + "_3.1",
Compile / compile / javacOptions ++=
Seq(
"-source",
"11",
"-target",
"11",
"-g:lines"
),
crossPaths := false, // exclude Scala suffix from artifact names
autoScalaLibrary := false, // exclude scala-library from dependencies
libraryDependencies += "com.heroku" % "webapp-runner" % "8.5.68.1"
)

lazy val warRunner_4_0 =
project
.in(file("runners/4.0"))
.settings(
name := "war-runner",
version := version.value + "_4.0",
Compile / compile / javacOptions ++=
Seq(
"-source",
"11",
"-target",
"11",
"-g:lines"
),
crossPaths := false, // exclude Scala suffix from artifact names
autoScalaLibrary := false, // exclude scala-library from dependencies
libraryDependencies += "com.heroku" % "webapp-runner" % "9.0.96.0"
)

lazy val warRunner_6_0 =
project
.in(file("runners/6.0"))
.settings(
name := "war-runner",
version := version.value + "_6.0",
Compile / compile / javacOptions ++=
Seq(
"-source",
Expand Down Expand Up @@ -51,8 +109,12 @@ lazy val sbtWar =
buildInfoPackage := "com.earldouglas.sbt.war",
buildInfoKeys := Seq[BuildInfoKey](version)
)
.dependsOn(warRunner)
.aggregate(warRunner)
.aggregate(
warRunner_3_0,
warRunner_3_1,
warRunner_4_0,
warRunner_6_0
)

// Publish to Sonatype, https://www.scala-sbt.org/release/docs/Using-Sonatype.html
ThisBuild / credentials := List(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.earldouglas;

import java.io.IOException;

/** Launches a webapp composed of in-place resources, classes, and libraries. */
public class WebappComponentsRunner {

/**
* Load configuration from the file in the first argument, and use it to start a new
* WebappComponentsRunner.
*
* @param args the configuration filename to load and run
* @throws IOException if something goes wrong
*/
public static void main(final String[] args) throws IOException {
throw new RuntimeException("unsupported");
}
}
71 changes: 71 additions & 0 deletions runners/3.1/src/main/java/com/earldouglas/WarConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.earldouglas;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class WarConfiguration {

/** The port to use for the server, e.g. 8080 */
public final int port;

/** The .war file to serve. */
public final File warFile;

/**
* Read configuration from a file at the specified location.
*
* @param configurationFilename the configuration filename to load
* @throws IOException if something goes wrong
* @return WarConfiguration a loaded configuration
*/
public static WarConfiguration load(final String configurationFilename) throws IOException {
return WarConfiguration.load(new File(configurationFilename));
}

/**
* Read configuration from a file at the specified location.
*
* <p>The format of the file is a Properties file with the following fields:
*
* <ul>
* <li>port
* <li>warFile
* </ul>
*
* <p>Example:
*
* <pre>
* port=8989
* warFile=path/to/warfile.war
* </pre>
*
* @param configurationFile the configuration file to load
* @throws IOException if something goes wrong
* @return WarConfiguration a loaded configuration
*/
public static WarConfiguration load(final File configurationFile) throws IOException {

final InputStream inputStream = new FileInputStream(configurationFile);

final Properties properties = new Properties();
properties.load(inputStream);

return new WarConfiguration(
Integer.parseInt(properties.getProperty("port")),
new File(properties.getProperty("warFile")));
}

/**
* Construct a new configuration from the given parameters.
*
* @param port the port to use for the server, e.g. 8080
* @param warFile the .war file to serve
*/
public WarConfiguration(final int port, final File warFile) {
this.port = port;
this.warFile = warFile;
}
}
22 changes: 22 additions & 0 deletions runners/3.1/src/main/java/com/earldouglas/WarRunner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.earldouglas;

public class WarRunner {

/**
* Load configuration from the file in the first argument, and use it to start a new WarRunner.
*
* @param args the configuration filename to load and run
* @throws Exception if something goes wrong
*/
public static void main(final String[] args) throws Exception {

final WarConfiguration warConfiguration = WarConfiguration.load(args[0]);

final String[] warRunnerArgs =
new String[] {
"--port", Integer.toString(warConfiguration.port), warConfiguration.warFile.getPath(),
};

webapp.runner.launch.Main.main(warRunnerArgs);
}
}
Empty file.
Empty file.
Empty file.
Empty file.
1 change: 1 addition & 0 deletions runners/3.1/src/test/fakeproject/src/main/webapp/bar.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<marquee>bar</marquee>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
div.raz { font-weight: bold; }
1 change: 1 addition & 0 deletions runners/3.1/src/test/fakeproject/src/main/webapp/foo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<blink>foo</blink>
2 changes: 2 additions & 0 deletions runners/3.1/src/test/resources/war.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
port=8988
warFile=src/test/fakeproject/src/main/webapp
8 changes: 8 additions & 0 deletions runners/3.1/src/test/resources/webapp-components.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
hostname=localhost
port=8989
contextPath=
emptyWebappDir=target/empty
emptyClassesDir=target/empty
resourceMap=bar.html->src/test/fakeproject/src/main/webapp/bar.html,\
foo.html->src/test/fakeproject/src/main/webapp/foo.html,\
baz/raz.css->src/test/fakeproject/src/main/webapp/baz/raz.css
64 changes: 64 additions & 0 deletions runners/3.1/src/test/scala/com/earldouglas/HttpClient.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.earldouglas

import java.net.HttpURLConnection
import java.net.URI
import scala.collection.JavaConverters._
import scala.io.Source

object HttpClient {

case class Response(
status: Int,
headers: Map[String, String],
body: String
)

def request(
method: String,
url: String,
headers: Map[String, String],
body: Option[String]
): Response = {

val c =
new URI(url)
.toURL()
.openConnection()
.asInstanceOf[HttpURLConnection]

c.setInstanceFollowRedirects(false)
c.setRequestMethod(method)
c.setDoInput(true)
c.setDoOutput(body.isDefined)

headers foreach { case (k, v) =>
c.setRequestProperty(k, v)
}

body foreach { b =>
c.getOutputStream.write(b.getBytes("UTF-8"))
}

val response =
Response(
status = c.getResponseCode(),
headers = c
.getHeaderFields()
.asScala
.filter({ case (k, _) => k != null })
.map({ case (k, v) => (k, v.asScala.mkString(",")) })
.toMap - "Date" - "Content-Length" - "Server",
body = Source.fromInputStream {
if (c.getResponseCode() < 400) {
c.getInputStream
} else {
c.getErrorStream
}
}.mkString
)

c.disconnect()

response
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.earldouglas

import org.scalatest.BeforeAndAfterAll
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers

import java.io.File

class WarConfigurationTest
extends AnyFunSuite
with Matchers
with BeforeAndAfterAll {

test("load") {

val configuration: WarConfiguration =
WarConfiguration.load("src/test/resources/war.properties")

configuration.port shouldBe 8988

configuration.warFile shouldBe
new File("src/test/fakeproject/src/main/webapp")
}
}
Loading
Loading