mirror of https://github.com/sbt/sbt.git
web app support split out to plugin
This commit is contained in:
parent
5e9b080fc8
commit
37823e5ffb
|
|
@ -53,8 +53,6 @@ class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths
|
|||
val cacheSub = project(cachePath, "Cache", new CacheProject(_), ioSub, collectionSub)
|
||||
// Builds on cache to provide caching for filesystem-related operations
|
||||
val trackingSub = baseProject(cachePath / "tracking", "Tracking", cacheSub, ioSub)
|
||||
// Interface to Jetty
|
||||
val webappSub = project("web", "Web App", new WebAppProject(_), ioSub, logSub, classpathSub, controlSub)
|
||||
// Embedded Scala code runner
|
||||
val runSub = baseProject("run", "Run", ioSub, logSub, classpathSub, processSub)
|
||||
|
||||
|
|
@ -146,37 +144,6 @@ class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths
|
|||
{
|
||||
val jline = jlineDep
|
||||
}
|
||||
class WebAppProject(info: ProjectInfo) extends Base(info)
|
||||
{
|
||||
val jetty = "org.mortbay.jetty" % "jetty" % "6.1.14" % "optional"
|
||||
val jettyplus = "org.mortbay.jetty" % "jetty-plus" % "6.1.14" % "optional"
|
||||
|
||||
val jetty7server = "org.eclipse.jetty" % "jetty-server" % "7.0.1.v20091125" % "optional"
|
||||
val jetty7webapp = "org.eclipse.jetty" % "jetty-webapp" % "7.0.1.v20091125" % "optional"
|
||||
val jetty7plus = "org.eclipse.jetty" % "jetty-plus" % "7.0.1.v20091125" % "optional"
|
||||
|
||||
val optional = Configurations.Optional
|
||||
|
||||
/* For generating JettyRun for Jetty 6 and 7. The only difference is the imports, but the file has to be compiled against each set of imports. */
|
||||
override def compileAction = super.compileAction dependsOn (generateJettyRun6, generateJettyRun7)
|
||||
def jettySrcDir = info.projectPath
|
||||
def jettyTemplate = jettySrcDir / "LazyJettyRun.scala.templ"
|
||||
|
||||
lazy val generateJettyRun6 = generateJettyRunN("6")
|
||||
lazy val generateJettyRun7 = generateJettyRunN("7")
|
||||
|
||||
def generateJettyRunN(n: String) =
|
||||
generateJettyRun(jettyTemplate, jettySrcDir / ("LazyJettyRun" + n + ".scala"), n, jettySrcDir / ("jetty" + n + ".imports"))
|
||||
|
||||
def generateJettyRun(in: Path, out: Path, version: String, importsPath: Path) =
|
||||
task
|
||||
{
|
||||
(for(template <- FileUtilities.readString(in asFile, log).right; imports <- FileUtilities.readString(importsPath asFile, log).right) yield
|
||||
FileUtilities.write(out asFile, processJettyTemplate(template, version, imports), log).toLeft(()) ).left.toOption
|
||||
}
|
||||
def processJettyTemplate(template: String, version: String, imports: String): String =
|
||||
template.replaceAll("""\Q${jetty.version}\E""", version).replaceAll("""\Q${jetty.imports}\E""", imports)
|
||||
}
|
||||
trait TestDependencies extends Project
|
||||
{
|
||||
val sc = "org.scala-tools.testing" % "scalacheck_2.8.0" % "1.7" % "test"
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<New id="testEnvEntry" class="org.eclipse.jetty.plus.jndi.EnvEntry">
|
||||
<Arg></Arg>
|
||||
<Arg>testValue</Arg>
|
||||
<Arg type="java.lang.String">It works</Arg>
|
||||
<Arg type="boolean">true</Arg>
|
||||
</New>
|
||||
|
||||
<!--
|
||||
<New id="DbNameDataSource" class="org.eclipse.jetty.plus.jndi.Resource">
|
||||
<Arg>jdbc/DbName</Arg>
|
||||
<Arg>
|
||||
<New class="com.mchange.v2.c3p0.ComboPooledDataSource">
|
||||
<Set name="driverClass">com.mysql.jdbc.Driver</Set>
|
||||
<Set name="jdbcUrl">jdbc:mysql://localhost/dbName</Set>
|
||||
<Set name="User">myUsername</Set>
|
||||
<Set name="Password">myPassword</Set>
|
||||
<Set name="maxPoolSize">30</Set>
|
||||
<Set name="checkoutTimeout">1800</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</New>
|
||||
<New id="DbNameDataSource" class="org.eclipse.jetty.plus.jndi.Resource">
|
||||
<Arg>jdbc/DbName</Arg>
|
||||
<Arg>
|
||||
<New class="com.mchange.v2.c3p0.ComboPooledDataSource">
|
||||
<Set name="driverClass">org.h2.Driver</Set>
|
||||
<Set name="jdbcUrl">jdbc:h2:tcp://localhost/~/dbName</Set>
|
||||
<Set name="jdbcUrl">jdbc:h2:mem:dbName</Set>
|
||||
<Set name="User">myUsername</Set>
|
||||
<Set name="Password">myPassword</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</New>
|
||||
-->
|
||||
</Configure>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
project.organization=sbt
|
||||
project.name=JettyEnvTest
|
||||
project.version=1.0
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
import sbt._
|
||||
import java.io.File
|
||||
import java.lang.System
|
||||
import Process._
|
||||
|
||||
class JettyEnvTestProject(info: ProjectInfo) extends DefaultWebProject(info){
|
||||
override def jettyEnvXml = Some( (info.projectPath / "conf" / "jetty" / "jetty-env.xml").asFile)
|
||||
val jetty7WebApp = "org.eclipse.jetty" % "jetty-webapp" % "7.0.2.RC0" % "test"
|
||||
val jetty7Plus = "org.eclipse.jetty" % "jetty-plus" % "7.0.2.RC0" % "test"
|
||||
val servletApiDep = "javax.servlet" % "servlet-api" % "2.5" % "provided"
|
||||
|
||||
def indexURL = new java.net.URL("http://localhost:" + jettyPort)
|
||||
def indexFile = new java.io.File("index.html")
|
||||
override def jettyPort = 7127
|
||||
lazy val getPage = execTask { indexURL #> indexFile }
|
||||
|
||||
lazy val checkPage = task { args => task { checkHelloWorld(args.mkString(" ")) } dependsOn getPage }
|
||||
|
||||
private def checkHelloWorld(checkString: String) =
|
||||
{
|
||||
val value = xsbt.FileUtilities.read(indexFile)
|
||||
if(value.contains(checkString)) None else Some("index.html did not contain '" + checkString + "' :\n" +value)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
import javax.servlet.http.{HttpServlet, HttpServletRequest => HSReq, HttpServletResponse => HSResp}
|
||||
import javax.naming.{InitialContext => IC};
|
||||
|
||||
class HelloJndi extends HttpServlet {
|
||||
|
||||
val key = "java:comp/env/testValue"
|
||||
val testValue = (new IC).lookup(key)
|
||||
|
||||
override def doGet(req : HSReq, resp : HSResp) =
|
||||
resp.getWriter().print("<HTML>" +
|
||||
"<HEAD><TITLE>Hello JNDI!</TITLE></HEAD>" +
|
||||
"<BODY>Hello JNDI, <br/>Value of " + key + ": " + testValue + "</BODY>" +
|
||||
"</HTML>")
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
<!DOCTYPE web-app
|
||||
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
|
||||
"http://java.sun.com/dtd/web-app_2_3.dtd">
|
||||
<web-app>
|
||||
<servlet>
|
||||
<servlet-name>helloJNDI</servlet-name>
|
||||
<servlet-class>HelloJndi</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>helloJNDI</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
</web-app>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
> ++2.7.7
|
||||
> update
|
||||
# verify that it fails without Jetty running
|
||||
-> check-page It works
|
||||
|
||||
> jetty-run
|
||||
# verify it now works with our servlet running
|
||||
> check-page It works
|
||||
> jetty-stop
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
<html>
|
||||
<body>
|
||||
<% out.println(" Hello World 2!"); %>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
project.name=JSP Test
|
||||
project.version=a
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
import sbt._
|
||||
|
||||
class JSP(info: ProjectInfo) extends DefaultWebProject(info)
|
||||
{
|
||||
val j6 = "org.mortbay.jetty" % "jetty" % "6.1.17" % "test->default"
|
||||
val j = "org.mortbay.jetty" % "jsp-2.0" % "6.1.17" % "test->default"
|
||||
|
||||
def indexURL = new java.net.URL("http://localhost:" + jettyPort)
|
||||
override def jettyPort = 7126
|
||||
def indexFile = new java.io.File("index.html")
|
||||
import Process._
|
||||
lazy val getPage = execTask { indexURL #> indexFile }
|
||||
|
||||
lazy val checkPage = task { args => task { checkHelloWorld(args.mkString(" ")) } dependsOn getPage }
|
||||
|
||||
private def checkHelloWorld(checkString: String) =
|
||||
{
|
||||
val value = xsbt.FileUtilities.read(indexFile)
|
||||
if(value.contains(checkString)) None else Some("index.html did not contain '" + checkString + "' :\n" +value)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
<html>
|
||||
<body>
|
||||
<% out.println(" Hello World!"); %>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
> update
|
||||
> jetty-run
|
||||
> check-page "Hello World!"
|
||||
|
||||
$ copy-file changes/index.jsp src/main/webapp/index.jsp
|
||||
|
||||
> prepare-webapp
|
||||
> jetty-reload
|
||||
> check-page "Hello World 2!"
|
||||
|
||||
> jetty-stop
|
||||
-> check-page "Hello World 2!"
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
package test
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
class MyServlet extends HttpServlet {
|
||||
|
||||
val html = <HTML>
|
||||
<HEAD><TITLE>Hello, Scala!</TITLE></HEAD>
|
||||
<BODY>Hello, Scala! This is a servlet.</BODY>
|
||||
</HTML>
|
||||
|
||||
override def doGet(req:HttpServletRequest, resp:HttpServletResponse) {
|
||||
resp.setContentType("text/html")
|
||||
resp.getWriter().print(html.toString)
|
||||
}
|
||||
def check28(f: Int = 3) = f
|
||||
}
|
||||
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
package test
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
class MyServlet extends HttpServlet {
|
||||
|
||||
val html = <HTML>
|
||||
<HEAD><TITLE>Hello, Scala 2!</TITLE></HEAD>
|
||||
<BODY>Hello, Scala 2! This is a servlet.</BODY>
|
||||
</HTML>
|
||||
|
||||
override def doGet(req:HttpServletRequest, resp:HttpServletResponse) {
|
||||
resp.setContentType("text/html")
|
||||
resp.getWriter().print(html.toString)
|
||||
}
|
||||
def check28(f: Int = 3) = f
|
||||
}
|
||||
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
project.organization=tester
|
||||
project.name=sbtweb
|
||||
project.version=1.0
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
import sbt._
|
||||
|
||||
class WebappBuild(info: ProjectInfo) extends DefaultWebProject(info) {
|
||||
|
||||
override def libraryDependencies = if("jetty7".asFile.exists) jetty7Dependencies else jetty6Dependencies
|
||||
def jetty6Dependencies =
|
||||
Set("org.mortbay.jetty" % "servlet-api-2.5" % "6.1.14" % "provided->default",
|
||||
"org.mortbay.jetty" % "jetty" % "6.1.14" % "test->default")
|
||||
def jetty7Dependencies =
|
||||
Set("javax.servlet" % "servlet-api" % "2.5" % "provided",
|
||||
"org.eclipse.jetty" % "jetty-server" % "7.0.1.v20091125" % "test",
|
||||
"org.eclipse.jetty" % "jetty-webapp" % "7.0.1.v20091125" % "test")
|
||||
|
||||
def indexURL = new java.net.URL("http://localhost:" + jettyPort)
|
||||
override def jettyPort = 7125
|
||||
def indexFile = new java.io.File("index.html")
|
||||
import Process._
|
||||
lazy val getPage = execTask { indexURL #> indexFile }
|
||||
lazy val checkPage = task { args => task { checkHelloWorld(args.mkString(" ")) } dependsOn getPage }
|
||||
|
||||
override def jettyWebappPath = webappPath
|
||||
|
||||
private def checkHelloWorld(checkString: String) =
|
||||
{
|
||||
val value = xsbt.FileUtilities.read(indexFile)
|
||||
if(value.contains(checkString)) None else Some("index.html did not contain '" + checkString + "' :\n" +value)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<!DOCTYPE web-app PUBLIC
|
||||
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
|
||||
"http://java.sun.com/dtd/web-app_2_3.dtd" >
|
||||
|
||||
<web-app>
|
||||
<display-name>Test Web Application</display-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Home</servlet-name>
|
||||
<servlet-class>test.MyServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>Home</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
> ++2.8.0.Beta1
|
||||
|
||||
$ copy-file changes/MyServlet1.scala src/main/scala/test/MyServlet.scala
|
||||
> update
|
||||
> jetty-run
|
||||
> check-page "Hello, Scala!"
|
||||
|
||||
$ copy-file changes/MyServlet2.scala src/main/scala/test/MyServlet.scala
|
||||
|
||||
> prepare-webapp
|
||||
> jetty-reload
|
||||
> check-page "Hello, Scala 2!"
|
||||
|
||||
> jetty-stop
|
||||
-> check-page "Hello World 2!"
|
||||
|
||||
$ touch jetty7
|
||||
$ copy-file changes/MyServlet1.scala src/main/scala/test/MyServlet.scala
|
||||
> update
|
||||
> jetty-run
|
||||
> check-page "Hello, Scala!"
|
||||
|
||||
$ copy-file changes/MyServlet2.scala src/main/scala/test/MyServlet.scala
|
||||
|
||||
> prepare-webapp
|
||||
> jetty-reload
|
||||
> check-page "Hello, Scala 2!"
|
||||
|
||||
> jetty-stop
|
||||
-> check-page "Hello World 2!"
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
package test
|
||||
|
||||
import java.util.Collections
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
class MyServlet extends HttpServlet {
|
||||
|
||||
val html = <HTML>
|
||||
<HEAD><TITLE>Hello, Scala!</TITLE></HEAD>
|
||||
<BODY>Hello, Scala! This is a servlet.</BODY>
|
||||
</HTML>
|
||||
|
||||
override def doGet(req:HttpServletRequest, resp:HttpServletResponse) {
|
||||
val found = Collections.list(getClass.getClassLoader.getResources("test/MyServlet.class"))
|
||||
assert( found.size == 1, "Multiple instances of MyServlet.class on classpath")
|
||||
resp.setContentType("text/html")
|
||||
resp.getWriter().print(html.toString)
|
||||
}
|
||||
def check28(f: Int = 3) = f
|
||||
}
|
||||
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
package test
|
||||
|
||||
import java.util.Collections
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
class MyServlet extends HttpServlet {
|
||||
|
||||
val html = <HTML>
|
||||
<HEAD><TITLE>Hello, Scala 2!</TITLE></HEAD>
|
||||
<BODY>Hello, Scala 2! This is a servlet.</BODY>
|
||||
</HTML>
|
||||
|
||||
override def doGet(req:HttpServletRequest, resp:HttpServletResponse) {
|
||||
val found = Collections.list(getClass.getClassLoader.getResources("test/MyServlet.class"))
|
||||
assert( found.size == 1, "Multiple instances of MyServlet.class on classpath")
|
||||
resp.setContentType("text/html")
|
||||
resp.getWriter().print(html.toString)
|
||||
}
|
||||
def check28(f: Int = 3) = f
|
||||
}
|
||||
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
project.organization=tester
|
||||
project.name=sbtweb
|
||||
project.version=1.0
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
import sbt._
|
||||
|
||||
class WebappBuild(info: ProjectInfo) extends DefaultWebProject(info) {
|
||||
|
||||
override def libraryDependencies = if("jetty7".asFile.exists) jetty7Dependencies else jetty6Dependencies
|
||||
def jetty6Dependencies =
|
||||
Set("org.mortbay.jetty" % "servlet-api-2.5" % "6.1.14" % "provided->default",
|
||||
"org.mortbay.jetty" % "jetty" % "6.1.14" % "test->default")
|
||||
def jetty7Dependencies =
|
||||
Set("javax.servlet" % "servlet-api" % "2.5" % "provided",
|
||||
"org.eclipse.jetty" % "jetty-server" % "7.0.1.v20091125" % "test",
|
||||
"org.eclipse.jetty" % "jetty-webapp" % "7.0.1.v20091125" % "test")
|
||||
|
||||
def indexURL = new java.net.URL("http://localhost:" + jettyPort)
|
||||
override def jettyPort = 7124
|
||||
def indexFile = new java.io.File("index.html")
|
||||
import Process._
|
||||
lazy val getPage = execTask { indexURL #> indexFile }
|
||||
lazy val checkPage = task { args => task { checkHelloWorld(args.mkString(" ")) } dependsOn getPage }
|
||||
|
||||
private def checkHelloWorld(checkString: String) =
|
||||
{
|
||||
val value = xsbt.FileUtilities.read(indexFile)
|
||||
if(value.contains(checkString)) None else Some("index.html did not contain '" + checkString + "' :\n" +value)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<!DOCTYPE web-app PUBLIC
|
||||
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
|
||||
"http://java.sun.com/dtd/web-app_2_3.dtd" >
|
||||
|
||||
<web-app>
|
||||
<display-name>Test Web Application</display-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Home</servlet-name>
|
||||
<servlet-class>test.MyServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>Home</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
> ++2.8.0.Beta1
|
||||
|
||||
$ copy-file changes/MyServlet1.scala src/main/scala/test/MyServlet.scala
|
||||
> update
|
||||
> jetty-run
|
||||
> check-page "Hello, Scala!"
|
||||
|
||||
$ copy-file changes/MyServlet2.scala src/main/scala/test/MyServlet.scala
|
||||
|
||||
> prepare-webapp
|
||||
> jetty-reload
|
||||
> check-page "Hello, Scala 2!"
|
||||
|
||||
> jetty-stop
|
||||
-> check-page "Hello World 2!"
|
||||
|
||||
# test that it works with Jetty 7 support
|
||||
$ touch jetty7
|
||||
|
||||
$ copy-file changes/MyServlet1.scala src/main/scala/test/MyServlet.scala
|
||||
> update
|
||||
> jetty-run
|
||||
> check-page "Hello, Scala!"
|
||||
|
||||
$ copy-file changes/MyServlet2.scala src/main/scala/test/MyServlet.scala
|
||||
|
||||
> prepare-webapp
|
||||
> jetty-reload
|
||||
> check-page "Hello, Scala 2!"
|
||||
|
||||
> jetty-stop
|
||||
-> check-page "Hello World 2!"
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
package test
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
class MyServlet extends HttpServlet {
|
||||
|
||||
val html = <HTML>
|
||||
<HEAD><TITLE>Hello, Scala!</TITLE></HEAD>
|
||||
<BODY>Hello, Scala! This is a servlet.</BODY>
|
||||
</HTML>
|
||||
|
||||
override def doGet(req:HttpServletRequest, resp:HttpServletResponse) {
|
||||
resp.setContentType("text/html")
|
||||
resp.getWriter().print(html.toString)
|
||||
}
|
||||
def check28(f: Int = 3) = f
|
||||
}
|
||||
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
package test
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
class MyServlet extends HttpServlet {
|
||||
|
||||
val html = <HTML>
|
||||
<HEAD><TITLE>Hello, Scala 2!</TITLE></HEAD>
|
||||
<BODY>Hello, Scala 2! This is a servlet.</BODY>
|
||||
</HTML>
|
||||
|
||||
override def doGet(req:HttpServletRequest, resp:HttpServletResponse) {
|
||||
resp.setContentType("text/html")
|
||||
resp.getWriter().print(html.toString)
|
||||
}
|
||||
def check28(f: Int = 3) = f
|
||||
}
|
||||
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
project.organization=tester
|
||||
project.name=sbtweb
|
||||
project.version=1.0
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
import sbt._
|
||||
|
||||
class WebappBuild(info: ProjectInfo) extends DefaultWebProject(info) {
|
||||
|
||||
override def libraryDependencies =
|
||||
if("jetty7.0".asFile.exists)
|
||||
jetty70Dependencies
|
||||
else if("jetty7.1".asFile.exists)
|
||||
jetty71Dependencies
|
||||
else
|
||||
jetty6Dependencies
|
||||
|
||||
def jetty6Dependencies =
|
||||
Set("org.mortbay.jetty" % "servlet-api-2.5" % "6.1.14" % "provided->default",
|
||||
"org.mortbay.jetty" % "jetty" % "6.1.14" % "test->default")
|
||||
def jetty70Dependencies =
|
||||
Set("javax.servlet" % "servlet-api" % "2.5" % "provided",
|
||||
"org.eclipse.jetty" % "jetty-webapp" % "7.0.1.v20091125" % "test")
|
||||
def jetty71Dependencies =
|
||||
Set("javax.servlet" % "servlet-api" % "2.5" % "provided",
|
||||
"org.eclipse.jetty" % "jetty-webapp" % "7.1.6.v20100715" % "test")
|
||||
|
||||
def indexURL = new java.net.URL("http://localhost:" + jettyPort)
|
||||
def indexFile = new java.io.File("index.html")
|
||||
override def jettyPort = 7123
|
||||
import Process._
|
||||
lazy val getPage = execTask { indexURL #> indexFile }
|
||||
lazy val checkPage = task { args => task { checkHelloWorld(args.mkString(" ")) } dependsOn getPage }
|
||||
|
||||
private def checkHelloWorld(checkString: String) =
|
||||
{
|
||||
val value = xsbt.FileUtilities.read(indexFile)
|
||||
if(value.contains(checkString)) None else Some("index.html did not contain '" + checkString + "' :\n" +value)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<!DOCTYPE web-app PUBLIC
|
||||
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
|
||||
"http://java.sun.com/dtd/web-app_2_3.dtd" >
|
||||
|
||||
<web-app>
|
||||
<display-name>Test Web Application</display-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Home</servlet-name>
|
||||
<servlet-class>test.MyServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>Home</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
> set build.scala.versions 2.8.0
|
||||
> reload
|
||||
|
||||
$ copy-file changes/MyServlet1.scala src/main/scala/test/MyServlet.scala
|
||||
> update
|
||||
> jetty-run
|
||||
> check-page "Hello, Scala!"
|
||||
|
||||
$ copy-file changes/MyServlet2.scala src/main/scala/test/MyServlet.scala
|
||||
|
||||
> prepare-webapp
|
||||
> jetty-reload
|
||||
> check-page "Hello, Scala 2!"
|
||||
|
||||
> jetty-stop
|
||||
-> check-page "Hello World 2!"
|
||||
|
||||
|
||||
# test that it works with Jetty 7 support
|
||||
$ touch jetty7.0
|
||||
> reload
|
||||
|
||||
$ copy-file changes/MyServlet1.scala src/main/scala/test/MyServlet.scala
|
||||
> update
|
||||
> jetty-run
|
||||
> check-page "Hello, Scala!"
|
||||
|
||||
$ copy-file changes/MyServlet2.scala src/main/scala/test/MyServlet.scala
|
||||
|
||||
> prepare-webapp
|
||||
> jetty-reload
|
||||
> check-page "Hello, Scala 2!"
|
||||
|
||||
> jetty-stop
|
||||
-> check-page "Hello World 2!"
|
||||
|
||||
|
||||
# test that it works with Jetty 7 support
|
||||
$ touch jetty7.1
|
||||
> reload
|
||||
|
||||
$ copy-file changes/MyServlet1.scala src/main/scala/test/MyServlet.scala
|
||||
> update
|
||||
> jetty-run
|
||||
> check-page "Hello, Scala!"
|
||||
|
||||
$ copy-file changes/MyServlet2.scala src/main/scala/test/MyServlet.scala
|
||||
|
||||
> prepare-webapp
|
||||
> jetty-reload
|
||||
> check-page "Hello, Scala 2!"
|
||||
|
||||
> jetty-stop
|
||||
-> check-page "Hello World 2!"
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
project.name=Webapp Unmanaged
|
||||
project.version=1.0
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
import sbt._
|
||||
|
||||
class UnmanagedTest(info: ProjectInfo) extends DefaultWebProject(info)
|
||||
{
|
||||
override def disableCrossPaths = true
|
||||
override def webappUnmanaged = temporaryWarPath / "WEB-INF" / "appengine-generated" ***
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
> prepare-webapp
|
||||
$ touch target/webapp/WEB-INF/appengine-generated/test-keep
|
||||
$ touch target/webapp/WEB-INF/other/test-remove
|
||||
> prepare-webapp
|
||||
$ exists target/webapp/WEB-INF/appengine-generated/test-keep
|
||||
$ absent target/webapp/WEB-INF/other/test-remove
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2008, 2009, 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
package jetty
|
||||
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
|
||||
/* This class starts Jetty.
|
||||
* NOTE: DO NOT actively use this class. You will see NoClassDefFoundErrors if you fail
|
||||
* to do so. Only use its name in JettyRun for reflective loading. This allows using
|
||||
* the Jetty libraries provided on the project classpath instead of requiring them to be
|
||||
* available on sbt's classpath at startup.
|
||||
*/
|
||||
private object LazyJettyRun${jetty.version} extends JettyRun
|
||||
{
|
||||
${jetty.imports}
|
||||
|
||||
import java.lang.ref.{Reference, WeakReference}
|
||||
|
||||
// Jetty classes must be loaded on initialization in order for the version detection code in WebApp to work properly
|
||||
// this forces them to be loaded- otherwise, it is possible they aren't loaded until 'apply' is called
|
||||
private[this] val forceJettyLoad = classOf[Server]
|
||||
|
||||
val DefaultMaxIdleTime = 30000
|
||||
|
||||
def apply(configuration: JettyConfiguration, jettyLoader: ClassLoader): Stoppable =
|
||||
{
|
||||
val oldLog = Log.getLog
|
||||
Log.setLog(new JettyLogger(configuration.log))
|
||||
val server = new Server
|
||||
|
||||
def configureScanner(listener: Scanner.BulkListener, scanDirectories: Seq[File], scanInterval: Int) =
|
||||
{
|
||||
if(scanDirectories.isEmpty)
|
||||
None
|
||||
else
|
||||
{
|
||||
configuration.log.debug("Scanning for changes to: " + scanDirectories.mkString(", "))
|
||||
val scanner = new Scanner
|
||||
val list = new java.util.ArrayList[File]
|
||||
scanDirectories.foreach(x => list.add(x))
|
||||
scanner.setScanDirs(list)
|
||||
scanner.setRecursive(true)
|
||||
scanner.setScanInterval(scanInterval)
|
||||
scanner.setReportExistingFilesOnStartup(false)
|
||||
scanner.addListener(listener)
|
||||
scanner.start()
|
||||
Some(new WeakReference(scanner))
|
||||
}
|
||||
}
|
||||
|
||||
val (listener, scanner) =
|
||||
configuration match
|
||||
{
|
||||
case c: DefaultJettyConfiguration =>
|
||||
import c._
|
||||
configureDefaultConnector(server, port)
|
||||
val webapp = new WebAppContext(war.absolutePath, contextPath)
|
||||
webDefaultXml.foreach{webDefaultXml:File => webapp.setDefaultsDescriptor(webDefaultXml.toString)}
|
||||
|
||||
def createLoader =
|
||||
{
|
||||
// Jetty treats WebAppClassLoader subclasses specially and we need this special behavior.
|
||||
// However, Jetty adds extra classpath components directly using 'addURL'.
|
||||
// We only want the 'urls' we provide in the constructor, so 'addURL' is overridden to do nothing.
|
||||
class SbtWebAppLoader(urls: Seq[URL]) extends WebAppClassLoader(jettyLoader, webapp)
|
||||
{
|
||||
urls.foreach(super.addURL)
|
||||
override def addURL(u: URL) = {}
|
||||
}
|
||||
new SbtWebAppLoader(classpath.getURLs)
|
||||
}
|
||||
def setLoader() = webapp.setClassLoader(createLoader)
|
||||
|
||||
setLoader()
|
||||
server.setHandler(webapp)
|
||||
|
||||
val listener = new Scanner.BulkListener with Reload {
|
||||
def reloadApp() = reload(server, setLoader(), log)
|
||||
def filesChanged(files: java.util.List[_]) { reloadApp() }
|
||||
}
|
||||
(Some(listener), configureScanner(listener, c.scanDirectories, c.scanInterval))
|
||||
case c: CustomJettyConfiguration =>
|
||||
for(x <- c.jettyConfigurationXML)
|
||||
(new XmlConfiguration(x.toString)).configure(server)
|
||||
for(file <- c.jettyConfigurationFiles)
|
||||
(new XmlConfiguration(file.toURI.toURL)).configure(server)
|
||||
(None, None)
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
server.start()
|
||||
new StopServer(new WeakReference(server), listener.map(new WeakReference(_)), scanner, oldLog)
|
||||
}
|
||||
catch { case e => server.stop(); throw e }
|
||||
}
|
||||
private def configureDefaultConnector(server: Server, port: Int)
|
||||
{
|
||||
val defaultConnector = new SelectChannelConnector
|
||||
defaultConnector.setPort(port)
|
||||
defaultConnector.setMaxIdleTime(DefaultMaxIdleTime)
|
||||
server.addConnector(defaultConnector)
|
||||
}
|
||||
trait Reload { def reloadApp(): Unit }
|
||||
private class StopServer(serverReference: Reference[Server], reloadReference: Option[Reference[Reload]], scannerReferenceOpt: Option[Reference[Scanner]], oldLog: JLogger) extends Stoppable
|
||||
{
|
||||
def reload(): Unit = on(reloadReference)(_.reloadApp())
|
||||
private def on[T](refOpt: Option[Reference[T]])(f: T => Unit): Unit = refOpt.foreach(ref => onReferenced(ref.get)(f))
|
||||
private def onReferenced[T](t: T)(f: T => Unit): Unit = if(t == null) () else f(t)
|
||||
def stop()
|
||||
{
|
||||
onReferenced(serverReference.get)(_.stop())
|
||||
on(scannerReferenceOpt)(_.stop())
|
||||
Log.setLog(oldLog)
|
||||
}
|
||||
}
|
||||
private def reload(server: Server, reconfigure: => Unit, log: Logger)
|
||||
{
|
||||
log.info("Reloading web application...")
|
||||
val handlers = wrapNull(server.getHandlers, server.getHandler)
|
||||
log.debug("Stopping handlers: " + handlers.mkString(", "))
|
||||
handlers.foreach(_.stop)
|
||||
log.debug("Reconfiguring...")
|
||||
reconfigure
|
||||
log.debug("Restarting handlers: " + handlers.mkString(", "))
|
||||
handlers.foreach(_.start)
|
||||
log.info("Reload complete.")
|
||||
}
|
||||
private def wrapNull(a: Array[Handler], b: Handler) =
|
||||
(a, b) match
|
||||
{
|
||||
case (null, null) => Nil
|
||||
case (null, notB) => notB :: Nil
|
||||
case (notA, null) => notA.toList
|
||||
case (notA, notB) => notB :: notA.toList
|
||||
}
|
||||
private class JettyLogger(delegate: AbstractLogger) extends JettyLoggerBase(delegate) with JLogger
|
||||
{
|
||||
def getLogger(name: String) = this
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
Simple Build Tool: Process Component
|
||||
Copyright 2008, 2009, 2010 Mark Harrah, Vesa Vilhonen
|
||||
Licensed under BSD-style license (see LICENSE)
|
||||
150
web/WebApp.scala
150
web/WebApp.scala
|
|
@ -1,150 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2008, 2009, 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import java.io.File
|
||||
import java.net.{URL, URLClassLoader}
|
||||
import scala.xml.NodeSeq
|
||||
import classpath.ClasspathUtilities
|
||||
|
||||
object JettyRunner
|
||||
{
|
||||
val DefaultPort = 8080
|
||||
val DefaultScanInterval = 3
|
||||
}
|
||||
class JettyRunner(configuration: JettyConfiguration) extends ExitHook
|
||||
{
|
||||
def name = "jetty-shutdown"
|
||||
def runBeforeExiting() { stop() }
|
||||
private var running: Option[Stoppable] = None
|
||||
private def started(s: Stoppable) { running = Some(s) }
|
||||
def stop()
|
||||
{
|
||||
running.foreach(_.stop())
|
||||
running = None
|
||||
}
|
||||
def reload() = running.foreach(_.reload())
|
||||
def apply(): Option[String] =
|
||||
{
|
||||
import configuration._
|
||||
def runJetty() =
|
||||
{
|
||||
val baseLoader = this.getClass.getClassLoader
|
||||
val jettyParentLoader = configuration match { case d: DefaultJettyConfiguration => d.parentLoader; case _ => ClassLoader.getSystemClassLoader }
|
||||
val jettyLoader: ClassLoader = ClasspathUtilities.toLoader(jettyClasspath, jettyParentLoader)
|
||||
|
||||
val jettyFilter = (name: String) => name.startsWith("org.mortbay.") || name.startsWith("org.eclipse.jetty.")
|
||||
val notJettyFilter = (name: String) => !jettyFilter(name)
|
||||
|
||||
val dual = new classpath.DualLoader(baseLoader, notJettyFilter, x => true, jettyLoader, jettyFilter, x => false)
|
||||
|
||||
def createRunner(implClassName: String) =
|
||||
{
|
||||
val lazyLoader = new classpath.LazyFrameworkLoader(implClassName, Array(IO.classLocation[Stoppable].toURI.toURL), dual, baseLoader)
|
||||
ModuleUtilities.getObject(implClassName, lazyLoader).asInstanceOf[JettyRun]
|
||||
}
|
||||
val runner = try { createRunner(implClassName6) } catch { case e: NoClassDefFoundError => createRunner(implClassName7) }
|
||||
runner(configuration, jettyLoader)
|
||||
}
|
||||
|
||||
if(running.isDefined)
|
||||
Some("This instance of Jetty is already running.")
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
started(runJetty())
|
||||
None
|
||||
}
|
||||
catch
|
||||
{
|
||||
case e: NoClassDefFoundError => runError(e, "Jetty and its dependencies must be on the " + classpathName + " classpath: ", log)
|
||||
case e => runError(e, "Error running Jetty: ", log)
|
||||
}
|
||||
}
|
||||
}
|
||||
private val implClassName6 = "sbt.jetty.LazyJettyRun6"
|
||||
private val implClassName7 = "sbt.jetty.LazyJettyRun7"
|
||||
|
||||
private def runError(e: Throwable, messageBase: String, log: Logger) =
|
||||
{
|
||||
log.trace(e)
|
||||
Some(messageBase + e.toString)
|
||||
}
|
||||
}
|
||||
|
||||
private trait Stoppable
|
||||
{
|
||||
def stop(): Unit
|
||||
def reload(): Unit
|
||||
}
|
||||
private trait JettyRun
|
||||
{
|
||||
def apply(configuration: JettyConfiguration, jettyLoader: ClassLoader): Stoppable
|
||||
}
|
||||
sealed trait JettyConfiguration extends NotNull
|
||||
{
|
||||
/** The classpath to get Jetty from. */
|
||||
def jettyClasspath: PathFinder
|
||||
def classpathName: String
|
||||
def log: AbstractLogger
|
||||
}
|
||||
trait DefaultJettyConfiguration extends JettyConfiguration
|
||||
{
|
||||
def war: Path
|
||||
def scanDirectories: Seq[File]
|
||||
def scanInterval: Int
|
||||
|
||||
|
||||
def contextPath: String
|
||||
def port: Int
|
||||
/** The classpath containing the classes, jars, and resources for the web application. */
|
||||
def classpath: PathFinder
|
||||
def parentLoader: ClassLoader
|
||||
def jettyEnv: Option[File]
|
||||
def webDefaultXml: Option[File]
|
||||
}
|
||||
abstract class CustomJettyConfiguration extends JettyConfiguration
|
||||
{
|
||||
def jettyConfigurationFiles: Seq[File] = Nil
|
||||
def jettyConfigurationXML: NodeSeq = NodeSeq.Empty
|
||||
}
|
||||
|
||||
private class JettyLoggerBase(delegate: AbstractLogger)
|
||||
{
|
||||
def getName = "JettyLogger"
|
||||
def isDebugEnabled = delegate.atLevel(Level.Debug)
|
||||
def setDebugEnabled(enabled: Boolean) = delegate.setLevel(if(enabled) Level.Debug else Level.Info)
|
||||
|
||||
def info(msg: String) { delegate.info(msg) }
|
||||
def debug(msg: String) { delegate.warn(msg) }
|
||||
def warn(msg: String) { delegate.warn(msg) }
|
||||
def info(msg: String, arg0: AnyRef, arg1: AnyRef) { delegate.info(format(msg, arg0, arg1)) }
|
||||
def debug(msg: String, arg0: AnyRef, arg1: AnyRef) { delegate.debug(format(msg, arg0, arg1)) }
|
||||
def warn(msg: String, arg0: AnyRef, arg1: AnyRef) { delegate.warn(format(msg, arg0, arg1)) }
|
||||
def info(msg: String, args: Array[AnyRef]) { delegate.info(format(msg, args: _*)) }
|
||||
def debug(msg: String, args: Array[AnyRef]) { delegate.debug(format(msg, args: _*)) }
|
||||
def warn(msg: String, args: Array[AnyRef]) { delegate.warn(format(msg, args: _*)) }
|
||||
def warn(msg: String, th: Throwable)
|
||||
{
|
||||
delegate.warn(msg)
|
||||
delegate.trace(th)
|
||||
}
|
||||
def debug(msg: String, th: Throwable)
|
||||
{
|
||||
delegate.debug(msg)
|
||||
delegate.trace(th)
|
||||
}
|
||||
private def format(msg: String, args: AnyRef*) =
|
||||
{
|
||||
def toString(arg: AnyRef) = if(arg == null) "" else arg.toString
|
||||
val pieces = msg.split("""\{\}""", args.length + 1).toList
|
||||
val argStrs = args.map(toString).toList ::: List("")
|
||||
pieces.zip(argStrs).foldLeft(new StringBuilder) { (sb, pair) =>
|
||||
val (piece, argStr) = pair
|
||||
if (piece.isEmpty) sb
|
||||
else sb.append(piece).append(argStr)
|
||||
}.toString
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
|
||||
import org.mortbay.jetty.{Handler, Server}
|
||||
import org.mortbay.jetty.nio.SelectChannelConnector
|
||||
import org.mortbay.jetty.webapp.{WebAppClassLoader, WebAppContext, WebInfConfiguration, Configuration, JettyWebXmlConfiguration, TagLibConfiguration, WebXmlConfiguration}
|
||||
import org.mortbay.log.{Log, Logger => JLogger}
|
||||
import org.mortbay.util.Scanner
|
||||
import org.mortbay.xml.XmlConfiguration
|
||||
import org.mortbay.jetty.plus.webapp.{EnvConfiguration, Configuration=>PlusConfiguration}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
import org.eclipse.jetty.server.{Server, Handler}
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector
|
||||
import org.eclipse.jetty.webapp.{WebAppClassLoader, WebAppContext, WebInfConfiguration, Configuration, FragmentConfiguration, JettyWebXmlConfiguration, TagLibConfiguration, WebXmlConfiguration}
|
||||
import org.eclipse.jetty.util.log.{Log, Logger => JLogger}
|
||||
import org.eclipse.jetty.util.Scanner
|
||||
import org.eclipse.jetty.xml.XmlConfiguration
|
||||
import org.eclipse.jetty.plus.webapp.{EnvConfiguration, Configuration=>PlusConfiguration}
|
||||
|
||||
Loading…
Reference in New Issue