Skip to content

Commit

Permalink
Issue 795 - Add support for MongoOptions in MongoDB
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Nelson committed Mar 2, 2011
1 parent e6deacf commit b043c81
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 29 deletions.
53 changes: 30 additions & 23 deletions persistence/mongodb/src/main/scala/net/liftweb/mongodb/Mongo.scala
@@ -1,5 +1,5 @@
/*
* Copyright 2010 WorldWide Conferencing, LLC
* Copyright 2010-2011 WorldWide Conferencing, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -14,8 +14,8 @@
* limitations under the License.
*/

package net.liftweb {
package mongodb {
package net.liftweb
package mongodb

import java.util.concurrent.ConcurrentHashMap

Expand Down Expand Up @@ -46,35 +46,38 @@ case object DefaultMongoIdentifier extends MongoIdentifier {
/*
* Wrapper for getting a reference to a db from the given Mongo instance
*/
trait MongoAddressBase {
def db: DB
}

case class MongoAddress(host: MongoHostBase, name: String) extends MongoAddressBase {
case class MongoAddress(host: MongoHostBase, name: String) {
def db = host.mongo.getDB(name)
}



/*
* Wrapper for creating a Mongo instance
*/
abstract class MongoHostBase {
def mongo: Mongo
}
case class MongoHost(host: String, port: Int) extends MongoHostBase {
lazy val mongo = new Mongo(host, port)
case class MongoHost(server: ServerAddress = new ServerAddress, options: MongoOptions = new MongoOptions) extends MongoHostBase {
lazy val mongo = new Mongo(server, options)
}
object MongoHost {
def apply(): MongoHost = MongoHost("127.0.0.1", 27017)
def apply(host: String): MongoHost = MongoHost(host, 27017)
def apply(host: String): MongoHost = MongoHost(new ServerAddress(host, 27017))
def apply(host: String, port: Int): MongoHost = MongoHost(new ServerAddress(host, port))
def apply(host: String, port: Int, options: MongoOptions): MongoHost = MongoHost(new ServerAddress(host, port), options)
}

/*
* Wrapper for creating a Paired Mongo instance
* Wrapper for creating a Replica Pair
*/
case class MongoPair(left: DBAddress, right: DBAddress) extends MongoHostBase {
lazy val mongo = new Mongo(left, right)
case class MongoPair(left: ServerAddress, right: ServerAddress, options: MongoOptions = new MongoOptions) extends MongoHostBase {
lazy val mongo = new Mongo(left, right, options)
}

/*
* Wrapper for creating a Replica Set
*/
case class MongoSet(dbs: List[ServerAddress], options: MongoOptions = new MongoOptions) extends MongoHostBase {
import scala.collection.JavaConversions._
lazy val mongo = new Mongo(dbs, options)
}

/*
Expand All @@ -85,19 +88,25 @@ object MongoDB {
/*
* HashMap of MongoAddresses, keyed by MongoIdentifier
*/
private val dbs = new ConcurrentHashMap[MongoIdentifier, MongoAddressBase]
private val dbs = new ConcurrentHashMap[MongoIdentifier, MongoAddress]

/*
* Define a Mongo db
*/
def defineDb(name: MongoIdentifier, address: MongoAddressBase) {
def defineDb(name: MongoIdentifier, address: MongoAddress) {
dbs.put(name, address)
}
/*
* Define a Mongo db using a standard Mongo instance.
*/
def defineDb(name: MongoIdentifier, mongo: Mongo, dbName: String) {
dbs.put(name, MongoAddress(new MongoHostBase { def mongo = mongo }, dbName))
}

/*
* Define and authenticate a Mongo db
*/
def defineDbAuth(name: MongoIdentifier, address: MongoAddressBase, username: String, password: String) {
def defineDbAuth(name: MongoIdentifier, address: MongoAddress, username: String, password: String) {
if (!address.db.authenticate(username, password.toCharArray))
throw new MongoException("Authorization failed: "+address.toString)

Expand All @@ -109,7 +118,7 @@ object MongoDB {
*/
def getDb(name: MongoIdentifier): Option[DB] = dbs.get(name) match {
case null => None
case ma: MongoAddressBase => Some(ma.db)
case ma: MongoAddress => Some(ma.db)
}

/*
Expand Down Expand Up @@ -221,5 +230,3 @@ object MongoDB {
dbs.clear
}
}
}
}
@@ -0,0 +1,94 @@
/*
* Copyright 2011 WorldWide Conferencing, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.liftweb
package mongodb

import org.specs.Specification
import org.specs.runner.JUnit4

import com.mongodb._

class MongoSpecsTest extends JUnit4(MongoSpecs)

object MongoSpecs extends Specification {

case object TestMongoIdentifier extends MongoIdentifier {
val jndiName = "test_a"
}

def passDefinitionTests(id: MongoIdentifier, ma: MongoAddress): Unit = {
// define the db
MongoDB.close
MongoDB.defineDb(id, ma)
// make sure it can be used
try {
MongoDB.use(id) { db =>
db.getLastError.ok must beEqualTo(true)
}
}
catch {
case e: MongoInternalException if (e.getMessage == "DBPort.findOne failed") => skip("MongoDB is not running")
case e: NullPointerException => skip("MongoDB is not running")
case e: MongoException if (e.getMessage == "can't find a master") => skip("MongoDB is not running")
}
// using an undefined identifier throws an exception
MongoDB.use(DefaultMongoIdentifier) { db =>
db.getLastError.ok must beEqualTo(true)
} must throwA(new MongoException("Mongo not found: MongoIdentifier(test)"))
// remove defined db
MongoDB.close
}

"Mongo" should {
"Define DB with default host and port" in {
passDefinitionTests(TestMongoIdentifier, MongoAddress(MongoHost(), "test_default"))
}
"Define DB with default port" in {
passDefinitionTests(TestMongoIdentifier, MongoAddress(MongoHost("127.0.0.1"), "test_default"))
}
"Define DB with specified host and port" in {
passDefinitionTests(TestMongoIdentifier, MongoAddress(MongoHost("127.0.0.1", 27017), "test_default"))
}
"Define DB pair with DBAddress" in {
val dba = new DBAddress("127.0.0.1", 27017, "test_a")
val dbb = new DBAddress("127.0.0.1", 27018, "test_b")
passDefinitionTests(TestMongoIdentifier, MongoAddress(MongoPair(dba, dbb), "test_default"))
}
"Define DB with ServerAddress and MongoOptions" in {
passDefinitionTests(TestMongoIdentifier, MongoAddress(MongoHost(new ServerAddress, new MongoOptions), "test_default"))
}
"Define DB with ServerAddress" in {
passDefinitionTests(TestMongoIdentifier, MongoAddress(MongoHost(new ServerAddress), "test_default"))
}
"Define DB with MongoOptions" in {
val mo = new MongoOptions
mo.connectionsPerHost = 12
passDefinitionTests(TestMongoIdentifier, MongoAddress(MongoHost(options=mo), "test_default"))
}
"Define DB pair with ServerAddress" in {
val dba = new ServerAddress("127.0.0.1", 27017)
val dbb = new ServerAddress("127.0.0.1", 27018)
passDefinitionTests(TestMongoIdentifier, MongoAddress(MongoPair(dba, dbb), "test_default"))
}
"Define DB set with ServerAddress" in {
val dba = new ServerAddress("127.0.0.1", 27017)
val dbb = new ServerAddress("127.0.0.1", 27018)
val dbc = new ServerAddress("127.0.0.1", 27019)
passDefinitionTests(TestMongoIdentifier, MongoAddress(MongoSet(List(dba, dbb, dbc)), "test_default"))
}
}
}
Expand Up @@ -37,11 +37,9 @@ trait MongoTestKit {
def debug = false

doBeforeSpec {
if (isMongoRunning) {
// define the dbs
dbs foreach { dbtuple =>
MongoDB.defineDb(dbtuple._1, MongoAddress(dbtuple._2, dbtuple._3))
}
// define the dbs
dbs foreach { dbtuple =>
MongoDB.defineDb(dbtuple._1, MongoAddress(dbtuple._2, dbtuple._3))
}
}

Expand All @@ -56,7 +54,7 @@ trait MongoTestKit {
true
}
} catch {
case _ => false
case e: Exception => false
}

def checkMongoIsRunning = isMongoRunning must beEqualTo(true).orSkipExample
Expand Down

0 comments on commit b043c81

Please sign in to comment.