From 31822b2e17301e5241ca414e55e823d581b5914f Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Mon, 1 Feb 2010 20:48:51 -0500 Subject: [PATCH] Jetty 7 support working --- .gitignore | 2 + src/main/scala/sbt/WebApp.scala | 2 +- .../scala/sbt/jetty/LazyJettyRun.scala.templ | 2 +- src/main/scala/sbt/jetty/LazyJettyRun6.scala | 137 ------------------ src/main/scala/sbt/jetty/LazyJettyRun7.scala | 137 ------------------ .../specs-run/project/build/TestProject.scala | 2 +- src/sbt-test/tests/specs-run/test | 3 +- .../MyServlet1.scala} | 0 .../{MyServlet.scala => MyServlet2.scala} | 0 .../project/build/src/WebappBuild.scala | 10 +- src/sbt-test/web/servlet-direct/test | 22 ++- .../MyServlet1.scala} | 0 .../{MyServlet.scala => MyServlet2.scala} | 0 .../project/build/src/WebappBuild.scala | 10 +- .../servlet/src/main/webapp/WEB-INF/web.xml | 2 +- src/sbt-test/web/servlet/test | 23 ++- 16 files changed, 64 insertions(+), 288 deletions(-) create mode 100644 .gitignore delete mode 100644 src/main/scala/sbt/jetty/LazyJettyRun6.scala delete mode 100644 src/main/scala/sbt/jetty/LazyJettyRun7.scala rename src/sbt-test/web/servlet-direct/{src/main/scala/test/MyServlet.scala => changes/MyServlet1.scala} (100%) rename src/sbt-test/web/servlet-direct/changes/{MyServlet.scala => MyServlet2.scala} (100%) rename src/sbt-test/web/servlet/{src/main/scala/test/MyServlet.scala => changes/MyServlet1.scala} (100%) rename src/sbt-test/web/servlet/changes/{MyServlet.scala => MyServlet2.scala} (100%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..130e42047 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +LazyJettyRun6.scala +LazyJettyRun7.scala diff --git a/src/main/scala/sbt/WebApp.scala b/src/main/scala/sbt/WebApp.scala index 5d53917ee..206092d1f 100644 --- a/src/main/scala/sbt/WebApp.scala +++ b/src/main/scala/sbt/WebApp.scala @@ -36,7 +36,7 @@ class JettyRunner(configuration: JettyConfiguration) extends ExitHook val jettyParentLoader = configuration match { case d: DefaultJettyConfiguration => d.parentLoader; case _ => ClassLoader.getSystemClassLoader } val jettyLoader: ClassLoader = new java.net.URLClassLoader(classpathURLs.toArray, jettyParentLoader) - val jettyFilter = (name: String) => name.startsWith("org.mortbay.") + val jettyFilter = (name: String) => name.startsWith("org.mortbay.") || name.startsWith("org.eclipse.jetty.") val notJettyFilter = (name: String) => !jettyFilter(name) val dual = new xsbt.DualLoader(baseLoader, notJettyFilter, x => true, jettyLoader, jettyFilter, x => false) diff --git a/src/main/scala/sbt/jetty/LazyJettyRun.scala.templ b/src/main/scala/sbt/jetty/LazyJettyRun.scala.templ index 29f86a4a8..09aec20ab 100644 --- a/src/main/scala/sbt/jetty/LazyJettyRun.scala.templ +++ b/src/main/scala/sbt/jetty/LazyJettyRun.scala.templ @@ -5,7 +5,7 @@ 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 +* 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. */ diff --git a/src/main/scala/sbt/jetty/LazyJettyRun6.scala b/src/main/scala/sbt/jetty/LazyJettyRun6.scala deleted file mode 100644 index 30ea2c787..000000000 --- a/src/main/scala/sbt/jetty/LazyJettyRun6.scala +++ /dev/null @@ -1,137 +0,0 @@ -package sbt.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 LazyJettyRun6 extends JettyRun -{ - - import org.mortbay.jetty.{Handler, Server} - import org.mortbay.jetty.nio.SelectChannelConnector - import org.mortbay.jetty.webapp.{WebAppClassLoader, WebAppContext} - import org.mortbay.log.{Log, Logger => JLogger} - import org.mortbay.util.Scanner - import org.mortbay.xml.XmlConfiguration - - import java.lang.ref.{Reference, WeakReference} - - 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) - def classpathURLs = classpath.get.map(_.asURL).toSeq - val webapp = new WebAppContext(war.absolutePath, contextPath) - - def createLoader = - { - class SbtWebAppLoader extends WebAppClassLoader(jettyLoader, webapp) { override def addURL(u: URL) = super.addURL(u) }; - val loader = new SbtWebAppLoader - classpathURLs.foreach(loader.addURL) - loader - } - 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: Logger) extends JettyLoggerBase(delegate) with JLogger - { - def getLogger(name: String) = this - } -} diff --git a/src/main/scala/sbt/jetty/LazyJettyRun7.scala b/src/main/scala/sbt/jetty/LazyJettyRun7.scala deleted file mode 100644 index 84ca8c7d5..000000000 --- a/src/main/scala/sbt/jetty/LazyJettyRun7.scala +++ /dev/null @@ -1,137 +0,0 @@ -package sbt.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 LazyJettyRun7 extends JettyRun -{ - - import org.eclipse.jetty.server.{Server, Handler} - import org.eclipse.jetty.server.nio.SelectChannelConnector - import org.eclipse.jetty.webapp.{WebAppClassLoader, WebAppContext} - import org.eclipse.jetty.util.log.{Log, Logger => JLogger} - import org.eclipse.jetty.util.Scanner - import org.eclipse.jetty.xml.XmlConfiguration - - import java.lang.ref.{Reference, WeakReference} - - 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) - def classpathURLs = classpath.get.map(_.asURL).toSeq - val webapp = new WebAppContext(war.absolutePath, contextPath) - - def createLoader = - { - class SbtWebAppLoader extends WebAppClassLoader(jettyLoader, webapp) { override def addURL(u: URL) = super.addURL(u) }; - val loader = new SbtWebAppLoader - classpathURLs.foreach(loader.addURL) - loader - } - 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: Logger) extends JettyLoggerBase(delegate) with JLogger - { - def getLogger(name: String) = this - } -} diff --git a/src/sbt-test/tests/specs-run/project/build/TestProject.scala b/src/sbt-test/tests/specs-run/project/build/TestProject.scala index cba60bdda..40a3de9f7 100644 --- a/src/sbt-test/tests/specs-run/project/build/TestProject.scala +++ b/src/sbt-test/tests/specs-run/project/build/TestProject.scala @@ -2,5 +2,5 @@ import sbt._ class TestProject(info: ProjectInfo) extends DefaultProject(info) { - val specs = "org.scala-tools.testing" %% "specs" % "1.6.1" + val specs = "org.scala-tools.testing" %% "specs" % "1.6.1" intransitive() } \ No newline at end of file diff --git a/src/sbt-test/tests/specs-run/test b/src/sbt-test/tests/specs-run/test index b3266bfb4..86d367a09 100644 --- a/src/sbt-test/tests/specs-run/test +++ b/src/sbt-test/tests/specs-run/test @@ -1,4 +1,5 @@ -> ++2.8.0.Beta1-RC7 +#> ++2.8.0.Beta1-RC7 +> ++2.7.7 > update > clean diff --git a/src/sbt-test/web/servlet-direct/src/main/scala/test/MyServlet.scala b/src/sbt-test/web/servlet-direct/changes/MyServlet1.scala similarity index 100% rename from src/sbt-test/web/servlet-direct/src/main/scala/test/MyServlet.scala rename to src/sbt-test/web/servlet-direct/changes/MyServlet1.scala diff --git a/src/sbt-test/web/servlet-direct/changes/MyServlet.scala b/src/sbt-test/web/servlet-direct/changes/MyServlet2.scala similarity index 100% rename from src/sbt-test/web/servlet-direct/changes/MyServlet.scala rename to src/sbt-test/web/servlet-direct/changes/MyServlet2.scala diff --git a/src/sbt-test/web/servlet-direct/project/build/src/WebappBuild.scala b/src/sbt-test/web/servlet-direct/project/build/src/WebappBuild.scala index bca37e84d..c420a8227 100644 --- a/src/sbt-test/web/servlet-direct/project/build/src/WebappBuild.scala +++ b/src/sbt-test/web/servlet-direct/project/build/src/WebappBuild.scala @@ -2,8 +2,14 @@ import sbt._ class WebappBuild(info: ProjectInfo) extends DefaultWebProject(info) { - val servlet_api = "org.mortbay.jetty" % "servlet-api-2.5" % "6.1.14" % "provided->default" - val jetty_servlet = "org.mortbay.jetty" % "jetty" % "6.1.14" % "test->default" + 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:8080") def indexFile = new java.io.File("index.html") diff --git a/src/sbt-test/web/servlet-direct/test b/src/sbt-test/web/servlet-direct/test index a04dfa4d7..78f55a2dc 100644 --- a/src/sbt-test/web/servlet-direct/test +++ b/src/sbt-test/web/servlet-direct/test @@ -1,10 +1,26 @@ -> ++2.8.0.Beta1-RC6 +> ++2.8.0.Beta1 + +$ copy-file changes/MyServlet1.scala src/main/scala/test/MyServlet.scala > update > jetty-run -$ pause > check-page "Hello, Scala!" -$ copy-file changes/MyServlet.scala src/main/scala/test/MyServlet.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 diff --git a/src/sbt-test/web/servlet/src/main/scala/test/MyServlet.scala b/src/sbt-test/web/servlet/changes/MyServlet1.scala similarity index 100% rename from src/sbt-test/web/servlet/src/main/scala/test/MyServlet.scala rename to src/sbt-test/web/servlet/changes/MyServlet1.scala diff --git a/src/sbt-test/web/servlet/changes/MyServlet.scala b/src/sbt-test/web/servlet/changes/MyServlet2.scala similarity index 100% rename from src/sbt-test/web/servlet/changes/MyServlet.scala rename to src/sbt-test/web/servlet/changes/MyServlet2.scala diff --git a/src/sbt-test/web/servlet/project/build/src/WebappBuild.scala b/src/sbt-test/web/servlet/project/build/src/WebappBuild.scala index 20edda2f6..4b0028732 100644 --- a/src/sbt-test/web/servlet/project/build/src/WebappBuild.scala +++ b/src/sbt-test/web/servlet/project/build/src/WebappBuild.scala @@ -2,8 +2,14 @@ import sbt._ class WebappBuild(info: ProjectInfo) extends DefaultWebProject(info) { - val servlet_api = "org.mortbay.jetty" % "servlet-api-2.5" % "6.1.14" % "provided->default" - val jetty_servlet = "org.mortbay.jetty" % "jetty" % "6.1.14" % "test->default" + 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:8080") def indexFile = new java.io.File("index.html") diff --git a/src/sbt-test/web/servlet/src/main/webapp/WEB-INF/web.xml b/src/sbt-test/web/servlet/src/main/webapp/WEB-INF/web.xml index bff12b49b..441ad39bd 100644 --- a/src/sbt-test/web/servlet/src/main/webapp/WEB-INF/web.xml +++ b/src/sbt-test/web/servlet/src/main/webapp/WEB-INF/web.xml @@ -3,7 +3,7 @@ "http://java.sun.com/dtd/web-app_2_3.dtd" > - Archetype Created Web Application + Test Web Application Home diff --git a/src/sbt-test/web/servlet/test b/src/sbt-test/web/servlet/test index 5e153ca61..39ebb15bd 100644 --- a/src/sbt-test/web/servlet/test +++ b/src/sbt-test/web/servlet/test @@ -1,9 +1,28 @@ -> ++2.8.0.Beta1-RC6 +> ++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/MyServlet.scala src/main/scala/test/MyServlet.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