package com.mastfrog.acteur.mongo;
import com.google.inject.AbstractModule;
import com.google.inject.name.Names;
import com.mastfrog.util.ConfigurationError;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.MongoClient;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Simple bindings for MongoDB
*
* @author Tim Boudreau
*/
public final class GiuliusMongoModule extends AbstractModule implements MongoConfigModule {
public static final String MONGO_HOST = "mongoHost";
public static final String MONGO_PORT = "mongoPort";
public static final String DATABASE_NAME = "_dbName";
public static final String SETTINGS_KEY_MONGO_USER = "mongo.user";
public static final String SETTINGS_KEY_MONGO_SSL = "mongo.ssl";
public static final String SETTINGS_KEY_MONGO_SSL_INVALID_HOSTNAMES_ALLOWED = "mongo.ssl.allow.invalid.hostnames";
public static final String SETTINGS_KEY_MONGO_PASSWORD = "mongo.password";
public static final String SETTINGS_KEY_MAX_WAIT_MILLIS = "mongo.max.wait.millis";
public static final int DEFAULT_MAX_WAIT_MILLIS = 20000;
public static final String SETTINGS_KEY_MAX_CONNECTIONS = "mongo.max.connections";
public static final int DEFAULT_MAX_CONNECTIONS = 1500;
private boolean configured;
private final Map<String, String> collectionForName = new HashMap<>();
private final String databaseName;
private final Set<Class<? extends MongoInitializer>> initializers = new HashSet<>();
/**
* Create a new module, attempting to find the main class name and use that
* as the database name.
*/
public GiuliusMongoModule() {
this(getMainClassName());
}
/**
* Create a new module, and use the specified database name
*
* @param databaseName
*/
public GiuliusMongoModule(String databaseName) {
this.databaseName = databaseName;
}
public GiuliusMongoModule addInitializer(Class<? extends MongoInitializer> type) {
initializers.add(type);
return this;
}
private static String getMainClassName() {
Exception e = new Exception();
StackTraceElement[] els = e.getStackTrace();
String className = els[els.length - 1].getClassName();
if (className.contains(".")) {
int ix = className.lastIndexOf(".");
if (ix < className.length() - 1) {
className = className.substring(ix + 1);
}
}
System.out.println("Using MongoDB database " + className.toLowerCase());
return className.toLowerCase();
}
/**
* Bind a collection so it can be injected using @Named, using the same
* name in code and as a collection name
*
* @param bindingName The name that will be used in code
* @return this
*/
public final GiuliusMongoModule bindCollection(String bindingName) {
return bindCollection(bindingName, bindingName);
}
/**
* Bind a collection so it can be injected using @Named
*
* @param bindingName The name that will be used in code
* @param collectionName The name of the actual collection
* @return this
*/
public final GiuliusMongoModule bindCollection(String bindingName, String collectionName) {
if (configured) {
throw new ConfigurationError("Cannot add bindings after application is started");
}
collectionForName.put(bindingName, collectionName);
return this;
}
public final String getDatabaseName() {
return databaseName;
}
@Override
protected void configure() {
configured = true;
bind(String.class).annotatedWith(Names.named(DATABASE_NAME)).toInstance(databaseName);
// We want to bail during startup if we can't contact the
// database, so use eager singleton to ensure we'll be
bind(MongoClient.class).toProvider(MongoClientProvider.class);
bind(DB.class).toProvider(DatabaseProvider.class);
bind(MongoInitializer.Registry.class).toInstance(new MongoInitializer.Registry());
for (Class<? extends MongoInitializer> c : initializers) {
bind(c).asEagerSingleton();
}
for (Map.Entry<String, String> e : collectionForName.entrySet()) {
CollectionProvider prov = new CollectionProvider(binder().getProvider(DB.class),
e.getValue(), binder().getProvider(MongoInitializer.Registry.class));
bind(DBCollection.class).annotatedWith(Names.named(e.getKey())).toProvider(
prov);
}
}
}