方法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 件のコメント:
コメントを投稿