方法1: カスタムjetty.xmlを使う
sbt標準だとjetty.xmlを1から書けばOK。override def jettyConfiguration = new CustomJettyConfiguration {
override def jettyConfigurationXML = List("/path/to/jetty.xml")
}
この方法だとjetty.xmlにConnectorとかHandlerとか全部自分で書かないといけないので面倒…
参考:jetty.xmlのリファレンス
方法2: sbtにちょっと手を入れてjetty設定用のhookを使う
sbtのソースをcheckoutしてhookが設定できるようにする
参考:Build - simple-build-tool -
sbtのソースをcheckout
$ git clone git://github.com/harrah/xsbt.git $ cd xsbt
変更したのは下の2行だけ。jetty-runが呼ばれてデフォルトのhttpポートのConnectorの設定直後にcallbackで設定した関数が呼ばれるようにする。
diff --git a/sbt/src/main/scala/sbt/WebApp.scala b/sbt/src/main/scala/sbt/WebApp.scala
index f5a3d09..997294e 100644
--- a/sbt/src/main/scala/sbt/WebApp.scala
+++ b/sbt/src/main/scala/sbt/WebApp.scala
@@ -105,6 +105,8 @@ trait DefaultJettyConfiguration extends JettyConfiguration
def parentLoader: ClassLoader
def jettyEnv: Option[File]
def webDefaultXml: Option[File]
+
+ def callback: Option[AnyRef => Any] = None
}
abstract class CustomJettyConfiguration extends JettyConfiguration
{
diff --git a/sbt/src/main/scala/sbt/jetty/LazyJettyRun.scala.templ b/sbt/src/main/scala/sbt/jetty/LazyJettyRun.scala.templ
index 263afa6..4ca4b0e 100644
--- a/sbt/src/main/scala/sbt/jetty/LazyJettyRun.scala.templ
+++ b/sbt/src/main/scala/sbt/jetty/LazyJettyRun.scala.templ
@@ -54,6 +54,7 @@ private object LazyJettyRun${jetty.version} extends JettyRun
case c: DefaultJettyConfiguration =>
import c._
configureDefaultConnector(server, port)
+ c.callback.foreach(_(server))
val webapp = new WebAppContext(war.absolutePath, contextPath)
webDefaultXml.foreach{webDefaultXml:File => webapp.setDefaultsDescriptor(webDefaultXml.toString)}
sbtのビルド
$ sbt update generate-loader-compat proguard "project Simple Build Tool" publish-local※generate-loader-compatしないとjetty6用のクラスが一部生成されなかった。(jettyは6->7でパッケージ名が変わったので、sbtのソースではテンプレート化して6,7,7.2用のscalaソースが吐かれるようになってる)
ssl用証明書の準備
JDKのkeytoolを使用。とりあえずオレオレ証明書で。$ keytool -keystore src/test/resources/keystore -alias jetty -genkey -keyalg RSA $ keytool -selfcert -validity 1024 -keystore src/test/resources/keystore -alias jetty※keystoreのパスワードを聞かれるので入力します
sbt プロジェクト側の準備
build.propertiesの sbt.version=0.7.5.RC0 にしてsbt実行、先に標準の0.7.5.RC0を入れておく。ビルドしたsbt/target/scala_2.7.7/sbt_2.7.7-0.7.5.RC0.jar をプロジェクトのproject/boot/scala-2.7.7/org.scala-tools.sbt/sbt/0.7.5.RC0/sbt_2.7.7-0.7.5.RC0.jar に上書き。
project/build/MyProject.scala の設定。callbackでjettyのServerインスタンスにSslSocketConnectorを追加。ClassLoaderが違うので普通に書くとClassCastExceptionが発生するのでリフレクションで。
override def jettyConfiguration: JettyConfiguration =
new DefaultJettyConfiguration {
def classpath = jettyRunClasspath
def jettyClasspath = MyProject.this.jettyClasspath
def war = jettyWebappPath
def contextPath = jettyContextPath
def classpathName = "test"
def parentLoader = buildScalaInstance.loader
def scanDirectories = Path.getFiles(MyProject.this.scanDirectories).toSeq
def scanInterval = MyProject.this.scanInterval
def port = jettyPort
def log = MyProject.this.log
def jettyEnv = jettyEnvXml
def webDefaultXml = jettyWebDefaultXml
override def callback = Some((server: AnyRef) => {
val cl = server.getClass.getClassLoader
val ssl = cl.loadClass("org.mortbay.jetty.security.SslSocketConnector").newInstance.asInstanceOf[{
def setPort(p: Int): Unit
def setMaxIdleTime(t: Int): Unit
def setKeystore(s: String): Unit
def setPassword(s: String): Unit
def setKeyPassword(s: String): Unit
def setTruststore(s: String): Unit
def setTrustPassword(s: String): Unit
}]
val addConnector: java.lang.reflect.Method = server.getClass.getMethod("addConnector", cl.loadClass("org.mortbay.jetty.Connector"))
ssl.setPort(8443)
ssl.setMaxIdleTime(30000)
ssl.setKeystore(info.projectPath + "/src/test/resources/keystore")
ssl.setPassword("password")
ssl.setKeyPassword("password")
ssl.setTruststore(info.projectPath + "/src/test/resources/keystore")
ssl.setTrustPassword("password")
addConnector.invoke(server, ssl)
})
}
※上記はjetty6の場合で、jetty7の場合はパッケージ・クラス名がちょっと違います。これで、jetty-runで8080でhttp、8443でhttpsが起動します。
0 件のコメント:
コメントを投稿