//Dstl (c) Crown Copyright 2017
package uk.gov.dstl.baleen.resources;
import java.util.Arrays;
import java.util.Map;
import org.apache.uima.fit.descriptor.ConfigurationParameter;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.resource.ResourceSpecifier;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoDatabase;
import uk.gov.dstl.baleen.core.utils.ConfigUtils;
import uk.gov.dstl.baleen.exceptions.BaleenException;
import uk.gov.dstl.baleen.uima.BaleenResource;
/**
* <b>Shared resource for accessing Mongo</b>
* <p>
* This resource removes the need for individual annotators to establish their
* own connections to Mongo, instead providing a single MongoClient instance for
* Baleen that can be used. This provides benefits such as reduced
* configuration, reduced repeated code, and support for connection pooling.</p>
*
*
* @baleen.javadoc
*/
public class SharedMongoResource extends BaleenResource {
private MongoClient m;
private MongoDatabase db;
/**
* The Mongo host to connect to
*
* @baleen.config localhost
*/
public static final String PARAM_HOST = "mongo.host";
@ConfigurationParameter(name = PARAM_HOST, defaultValue="localhost")
private String mongoHost;
/**
* The port to connect to Mongo on
*
* @baleen.config 27017
*/
public static final String PARAM_PORT = "mongo.port";
@ConfigurationParameter(name = PARAM_PORT, defaultValue="27017")
private String mongoPortString;
//Parse the port config parameter into this variable to avoid issues with parameter types
private int mongoPort;
/**
* The Mongo database to connect to
*
* @baleen.config baleen
*/
public static final String PARAM_DB = "mongo.db";
@ConfigurationParameter(name = PARAM_DB, defaultValue="baleen")
private String mongoDb;
/**
* The username to use for authentication.
* If left blank, then authentication will not be used.
*
* @baleen.config
*/
public static final String PARAM_USER = "mongo.user";
@ConfigurationParameter(name = PARAM_USER, defaultValue="")
private String mongoUser;
/**
* The password to use for authentication.
* If left blank, then authentication will not be used.
*
* @baleen.config
*/
public static final String PARAM_PASS = "mongo.pass";
@ConfigurationParameter(name = PARAM_PASS, defaultValue="")
private String mongoPass;
@Override
protected boolean doInitialize(ResourceSpecifier aSpecifier, Map<String, Object> aAdditionalParams) throws ResourceInitializationException {
mongoPort = ConfigUtils.stringToInteger(mongoPortString, 27017);
try{
connectToMongo(mongoHost, mongoPort, mongoDb, mongoUser, mongoPass);
}catch(BaleenException be){
throw new ResourceInitializationException(be);
}
getMonitor().info("Initialised shared Mongo resource");
return true;
}
private void connectToMongo(String host, int port, String database, String username, String password) throws BaleenException{
try {
// Connect to Mongo
ServerAddress sa = new ServerAddress(host, port);
Optional<MongoCredential> cred = createCredentials(username, password, database);
m = createMongoClient(sa, cred);
getMonitor().debug("Getting Mongo Database '{}'", db);
db = m.getDatabase(database);
} catch (Exception e) {
throw new BaleenException("Unable to connect to Mongo", e);
}
}
protected MongoClient createMongoClient(ServerAddress sa, Optional<MongoCredential> credentials){
if (!credentials.isPresent()) {
getMonitor().debug("Connecting to Mongo without authentication");
return new MongoClient(sa);
} else {
getMonitor().debug("Connecting to Mongo with authentication as user '{}'", credentials.get().getUserName());
return new MongoClient(sa, Arrays.asList(credentials.get()));
}
}
/**
* Creates a MongoCredential if a username, password and database are supplied, or returns absent() otherwise
*
* @param username The username to connect to Mongo with
* @param password The password to connect to Mongo with
* @param database The database to connect to
*/
public static Optional<MongoCredential> createCredentials(String username, String password, String database){
if (!Strings.isNullOrEmpty(username) && !Strings.isNullOrEmpty(password) && !Strings.isNullOrEmpty(database)) {
return Optional.of(MongoCredential.createMongoCRCredential(username, database, password.toCharArray()));
}else{
return Optional.absent();
}
}
@Override
protected void doDestroy() {
getMonitor().debug("Disconnecting from Mongo");
m.close();
db = null;
m = null;
}
/**
* Get the Mongo DB accessor.
*
* @return the monogo db, or null if the source has been destroyed or an
* initialisation error occurred.
*/
public MongoDatabase getDB() {
return db;
}
/**
* Creates a Mongo URI string, without the username:password
*
* @return
*/
public String getMongoURI(){
return "mongodb://" + mongoHost + ":" + mongoPort + "/" + mongoDb;
}
}