diff --git a/project/build.scala b/project/build.scala index 8a4844c..e767078 100644 --- a/project/build.scala +++ b/project/build.scala @@ -49,6 +49,8 @@ "org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "container;provided", "org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" % "container;provided;test" artifacts Artifact("javax.servlet", "jar", "jar"), "junit" % "junit" % "4.11" % "test", + "com.mchange" % "c3p0" % "0.9.5", + "com.typesafe" % "config" % "1.2.1", "com.typesafe.play" %% "twirl-compiler" % "1.0.2" ), EclipseKeys.withSource := true, diff --git a/src/main/resources/database.conf b/src/main/resources/database.conf new file mode 100644 index 0000000..0eca733 --- /dev/null +++ b/src/main/resources/database.conf @@ -0,0 +1,6 @@ +db { + driver = "org.h2.Driver" + url = "jdbc:h2:${DatabaseHome};MVCC=true" + user = "sa" + password = "sa" +} diff --git a/src/main/scala/servlet/AutoUpdateListener.scala b/src/main/scala/servlet/AutoUpdateListener.scala index 6020a0f..c71de94 100644 --- a/src/main/scala/servlet/AutoUpdateListener.scala +++ b/src/main/scala/servlet/AutoUpdateListener.scala @@ -10,7 +10,7 @@ import util.ControlUtil._ import util.JDBCUtil._ import org.eclipse.jgit.api.Git -import util.Directory +import util.{DatabaseConfig, Directory} object AutoUpdate { @@ -208,10 +208,7 @@ } org.h2.Driver.load() - val context = event.getServletContext - context.setInitParameter("db.url", s"jdbc:h2:${DatabaseHome};MVCC=true") - - defining(getConnection(event.getServletContext)){ conn => + defining(getConnection()){ conn => logger.debug("Start schema update") try { defining(getCurrentVersion()){ currentVersion => @@ -239,16 +236,10 @@ def contextDestroyed(sce: ServletContextEvent): Unit = { } - private def getConnection(servletContext: ServletContext): Connection = + private def getConnection(): Connection = DriverManager.getConnection( - servletContext.getInitParameter("db.url"), - servletContext.getInitParameter("db.user"), - servletContext.getInitParameter("db.password")) - - private def getDatabase(servletContext: ServletContext): scala.slick.jdbc.JdbcBackend.Database = - slick.jdbc.JdbcBackend.Database.forURL( - servletContext.getInitParameter("db.url"), - servletContext.getInitParameter("db.user"), - servletContext.getInitParameter("db.password")) + DatabaseConfig.url, + DatabaseConfig.user, + DatabaseConfig.password) } diff --git a/src/main/scala/servlet/TransactionFilter.scala b/src/main/scala/servlet/TransactionFilter.scala index b4712e9..20d37f5 100644 --- a/src/main/scala/servlet/TransactionFilter.scala +++ b/src/main/scala/servlet/TransactionFilter.scala @@ -1,27 +1,29 @@ package servlet import javax.servlet._ -import org.slf4j.LoggerFactory import javax.servlet.http.HttpServletRequest -import util.Keys +import com.mchange.v2.c3p0.ComboPooledDataSource +import org.slf4j.LoggerFactory +import slick.jdbc.JdbcBackend.{Database => SlickDatabase, Session} +import util.{DatabaseConfig, Keys} /** * Controls the transaction with the open session in view pattern. */ class TransactionFilter extends Filter { - + private val logger = LoggerFactory.getLogger(classOf[TransactionFilter]) - + def init(config: FilterConfig) = {} - + def destroy(): Unit = {} - + def doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain): Unit = { if(req.asInstanceOf[HttpServletRequest].getRequestURI().startsWith("/assets/")){ // assets don't need transaction chain.doFilter(req, res) } else { - Database(req.getServletContext) withTransaction { session => + Database() withTransaction { session => logger.debug("begin transaction") req.setAttribute(Keys.Request.DBSession, session) chain.doFilter(req, res) @@ -34,12 +36,24 @@ object Database { - def apply(context: ServletContext): slick.jdbc.JdbcBackend.Database = - slick.jdbc.JdbcBackend.Database.forURL(context.getInitParameter("db.url"), - context.getInitParameter("db.user"), - context.getInitParameter("db.password")) + private val logger = LoggerFactory.getLogger(Database.getClass) - def getSession(req: ServletRequest): slick.jdbc.JdbcBackend#Session = - req.getAttribute(Keys.Request.DBSession).asInstanceOf[slick.jdbc.JdbcBackend#Session] + private val db: SlickDatabase = { + val datasource = new ComboPooledDataSource + + datasource.setDriverClass(DatabaseConfig.driver) + datasource.setJdbcUrl(DatabaseConfig.url) + datasource.setUser(DatabaseConfig.user) + datasource.setPassword(DatabaseConfig.password) + + logger.debug("load database connection pool") + + SlickDatabase.forDataSource(datasource) + } + + def apply(): SlickDatabase = db + + def getSession(req: ServletRequest): Session = + req.getAttribute(Keys.Request.DBSession).asInstanceOf[Session] } diff --git a/src/main/scala/ssh/GitCommand.scala b/src/main/scala/ssh/GitCommand.scala index d1d4233..0e287fe 100644 --- a/src/main/scala/ssh/GitCommand.scala +++ b/src/main/scala/ssh/GitCommand.scala @@ -31,7 +31,7 @@ private def newTask(user: String): Runnable = new Runnable { override def run(): Unit = { - Database(context) withSession { implicit session => + Database() withSession { implicit session => try { runTask(user) callback.onExit(0) @@ -130,4 +130,4 @@ case _ => new UnknownCommand(command) } } -} \ No newline at end of file +} diff --git a/src/main/scala/ssh/PublicKeyAuthenticator.scala b/src/main/scala/ssh/PublicKeyAuthenticator.scala index 9b4520e..3781a79 100644 --- a/src/main/scala/ssh/PublicKeyAuthenticator.scala +++ b/src/main/scala/ssh/PublicKeyAuthenticator.scala @@ -10,7 +10,7 @@ class PublicKeyAuthenticator(context: ServletContext) extends PublickeyAuthenticator with SshKeyService { override def authenticate(username: String, key: PublicKey, session: ServerSession): Boolean = { - Database(context) withSession { implicit session => + Database() withSession { implicit session => getPublicKeys(username).exists { sshKey => SshUtil.str2PublicKey(sshKey.publicKey) match { case Some(publicKey) => key.equals(publicKey) diff --git a/src/main/scala/util/DatabaseConfig.scala b/src/main/scala/util/DatabaseConfig.scala new file mode 100644 index 0000000..86453e3 --- /dev/null +++ b/src/main/scala/util/DatabaseConfig.scala @@ -0,0 +1,19 @@ +package util + +import com.typesafe.config.ConfigFactory +import util.Directory.DatabaseHome + +object DatabaseConfig { + + private val config = ConfigFactory.load("database") + private val dbUrl = config.getString("db.url") + + def url(directory: Option[String]): String = + dbUrl.replace("${DatabaseHome}", directory.getOrElse(DatabaseHome)) + + val url: String = url(None) + val user: String = config.getString("db.user") + val password: String = config.getString("db.password") + val driver: String = config.getString("db.driver") + +} diff --git a/src/main/scala/util/Notifier.scala b/src/main/scala/util/Notifier.scala index 95ec6bf..f9e4348 100644 --- a/src/main/scala/util/Notifier.scala +++ b/src/main/scala/util/Notifier.scala @@ -27,7 +27,7 @@ getComments(issue.userName, issue.repositoryName, issue.issueId).map(_.commentedUserName) ) .distinct - .withFilter ( _ != context.loginAccount.get.userName ) // the operation in person is excluded + .withFilter ( _ != context.loginAccount.get.userName ) // the operation in person is excluded .foreach ( getAccountByUserName(_) filterNot (_.isGroupAccount) filterNot (LDAPUtil.isDummyMailAddress(_)) foreach (x => notify(x.mailAddress)) ) } @@ -67,7 +67,7 @@ def toNotify(r: RepositoryService.RepositoryInfo, issueId: Int, content: String) (msg: String => String)(implicit context: Context) = { - val database = Database(context.request.getServletContext) + val database = Database() val f = Future { database withSession { implicit session => @@ -113,4 +113,4 @@ class MockMailer extends Notifier { def toNotify(r: RepositoryService.RepositoryInfo, issueId: Int, content: String) (msg: String => String)(implicit context: Context): Unit = {} -} \ No newline at end of file +} diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 398ffd8..51513a1 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -45,25 +45,7 @@ GitRepositoryServlet /git/* - - - - - - db.user - sa - - - - db.password - sa - - - - db.tcpServer - -tcpAllowOthers - - + @@ -105,4 +87,4 @@ --> - \ No newline at end of file + diff --git a/src/test/scala/service/ServiceSpecBase.scala b/src/test/scala/service/ServiceSpecBase.scala index 4671059..be69750 100644 --- a/src/test/scala/service/ServiceSpecBase.scala +++ b/src/test/scala/service/ServiceSpecBase.scala @@ -3,6 +3,7 @@ import model.Profile._ import profile.simple._ import util.ControlUtil._ +import util.DatabaseConfig import java.sql.DriverManager import org.apache.commons.io.FileUtils import scala.util.Random @@ -12,7 +13,7 @@ def withTestDB[A](action: (Session) => A): A = { util.FileUtil.withTmpDir(new File(FileUtils.getTempDirectory(), Random.alphanumeric.take(10).mkString)){ dir => - val (url, user, pass) = (s"jdbc:h2:${dir}", "sa", "sa") + val (url, user, pass) = (DatabaseConfig.url(Some(dir.toString)), DatabaseConfig.user, DatabaseConfig.password) org.h2.Driver.load() using(DriverManager.getConnection(url, user, pass)){ conn => servlet.AutoUpdate.versions.reverse.foreach(_.update(conn))