package org.frameworkset.nosql.mongodb;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import com.frameworkset.util.StringUtil;
import com.mongodb.Bytes;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoClientOptions.Builder;
import com.mongodb.MongoCredential;
import com.mongodb.ReadPreference;
import com.mongodb.ServerAddress;
import com.mongodb.WriteConcern;
import com.mongodb.WriteConcernException;
import com.mongodb.WriteResult;
public class MongoDB {
private static Method autoConnectRetryMethod;
static {
try {
autoConnectRetryMethod = Builder.class.getMethod("autoConnectRetry", boolean.class);
} catch (NoSuchMethodException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
} catch (SecurityException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
}
}
private static Logger log = Logger.getLogger(MongoDB.class);
private String serverAddresses;
private String option;
private String writeConcern;
private String readPreference;
private Mongo mongoclient;
private String mode = null;
private boolean autoConnectRetry = true;
private int connectionsPerHost = 500;
private int maxWaitTime = 120000;
private int socketTimeout = 0;
private int connectTimeout = 15000;
private int threadsAllowedToBlockForConnectionMultiplier = 50;
private boolean socketKeepAlive = true;
private List<ClientMongoCredential> credentials;
private List<MongoCredential> mongoCredentials;
public MongoDB getMongoClient() {
// try {
// Mongo mongoClient = new Mongo(Arrays.asList(new
// ServerAddress("10.0.15.134", 27017),
// new ServerAddress("10.0.15.134", 27018),
// new ServerAddress("10.0.15.38", 27017),new
// ServerAddress("10.0.15.39", 27017)
// ));
// mongoClient.addOption( Bytes.QUERYOPTION_SLAVEOK );
// mongoClient.setWriteConcern(WriteConcern.JOURNAL_SAFE);
//// ReadPreference.secondaryPreferred();
// mongoClient.setReadPreference(ReadPreference.nearest());
//// mongoClient.setReadPreference(ReadPreference.primaryPreferred());
// return mongoClient;
// } catch (Exception e) {
// throw new java.lang.RuntimeException(e);
// }
return this;
}
public Mongo getMongo() {
// try {
// Mongo mongoClient = new Mongo(Arrays.asList(new
// ServerAddress("10.0.15.134", 27017),
// new ServerAddress("10.0.15.134", 27018),
// new ServerAddress("10.0.15.38", 27017),new
// ServerAddress("10.0.15.39", 27017)
// ));
// mongoClient.addOption( Bytes.QUERYOPTION_SLAVEOK );
// mongoClient.setWriteConcern(WriteConcern.JOURNAL_SAFE);
//// ReadPreference.secondaryPreferred();
// mongoClient.setReadPreference(ReadPreference.nearest());
//// mongoClient.setReadPreference(ReadPreference.primaryPreferred());
// return mongoClient;
// } catch (Exception e) {
// throw new java.lang.RuntimeException(e);
// }
return this.mongoclient;
}
private List<ServerAddress> parserAddress() throws NumberFormatException, UnknownHostException {
if (StringUtil.isEmpty(serverAddresses))
return null;
serverAddresses = serverAddresses.trim();
List<ServerAddress> trueaddresses = new ArrayList<ServerAddress>();
if (mode != null && mode.equals("simple")) {
String info[] = serverAddresses.split(":");
ServerAddress ad = new ServerAddress(info[0].trim(), Integer.parseInt(info[1].trim()));
trueaddresses.add(ad);
return trueaddresses;
}
String[] addresses = this.serverAddresses.split("\n");
for (String address : addresses) {
address = address.trim();
String info[] = address.split(":");
ServerAddress ad = new ServerAddress(info[0].trim(), Integer.parseInt(info[1].trim()));
trueaddresses.add(ad);
}
return trueaddresses;
}
private int[] parserOption() throws NumberFormatException, UnknownHostException {
if (StringUtil.isEmpty(this.option))
return null;
option = option.trim();
String[] options = this.option.split("\r\n");
int[] ret = new int[options.length];
int i = 0;
for (String op : options) {
op = op.trim();
ret[i] = _getOption(op);
i++;
}
return ret;
}
private int _getOption(String op) {
if (op.equals("QUERYOPTION_TAILABLE"))
return Bytes.QUERYOPTION_TAILABLE;
else if (op.equals("QUERYOPTION_SLAVEOK"))
return Bytes.QUERYOPTION_SLAVEOK;
else if (op.equals("QUERYOPTION_OPLOGREPLAY"))
return Bytes.QUERYOPTION_OPLOGREPLAY;
else if (op.equals("QUERYOPTION_NOTIMEOUT"))
return Bytes.QUERYOPTION_NOTIMEOUT;
else if (op.equals("QUERYOPTION_AWAITDATA"))
return Bytes.QUERYOPTION_AWAITDATA;
else if (op.equals("QUERYOPTION_EXHAUST"))
return Bytes.QUERYOPTION_EXHAUST;
else if (op.equals("QUERYOPTION_PARTIAL"))
return Bytes.QUERYOPTION_PARTIAL;
else if (op.equals("RESULTFLAG_CURSORNOTFOUND"))
return Bytes.RESULTFLAG_CURSORNOTFOUND;
else if (op.equals("RESULTFLAG_ERRSET"))
return Bytes.RESULTFLAG_ERRSET;
else if (op.equals("RESULTFLAG_SHARDCONFIGSTALE"))
return Bytes.RESULTFLAG_SHARDCONFIGSTALE;
else if (op.equals("RESULTFLAG_AWAITCAPABLE"))
return Bytes.RESULTFLAG_AWAITCAPABLE;
throw new RuntimeException("未知的option:" + op);
}
public static void main(String[] args) {
String aa = "REPLICA_ACKNOWLEDGED(10)";
int idx = aa.indexOf("(");
String n = aa.substring(idx + 1, aa.length() - 1);
System.out.println(n);
}
private WriteConcern _getWriteConcern() {
if (StringUtil.isEmpty(this.writeConcern))
return null;
writeConcern = writeConcern.trim();
if (this.writeConcern.equals("NONE"))
return WriteConcern.UNACKNOWLEDGED;
else if (this.writeConcern.equals("NORMAL"))
return WriteConcern.NORMAL;
else if (this.writeConcern.equals("SAFE"))
return WriteConcern.SAFE;
else if (this.writeConcern.equals("MAJORITY"))
return WriteConcern.MAJORITY;
else if (this.writeConcern.equals("FSYNC_SAFE"))
return WriteConcern.FSYNC_SAFE;
else if (this.writeConcern.equals("JOURNAL_SAFE"))
return WriteConcern.JOURNAL_SAFE;
else if (this.writeConcern.equals("REPLICAS_SAFE"))
return WriteConcern.REPLICAS_SAFE;
else if (this.writeConcern.startsWith("REPLICA_ACKNOWLEDGED")) {
int idx = writeConcern.indexOf("(");
if (idx < 0) {
return WriteConcern.REPLICA_ACKNOWLEDGED;
} else {
String n = this.writeConcern.substring(idx + 1, writeConcern.length() - 1);
try {
if (n.indexOf(",") < 0) {
int N = Integer.parseInt(n);
return new WriteConcern(N);
} else {
String[] p = n.split(",");
n = p[0];
String _wtimeout = p[1];
int N = Integer.parseInt(n);
int wtimeout = Integer.parseInt(_wtimeout);
return new WriteConcern(N, wtimeout, false);
}
} catch (NumberFormatException e) {
return WriteConcern.REPLICA_ACKNOWLEDGED;
}
}
} else if (this.writeConcern.equals("ACKNOWLEDGED"))
return WriteConcern.ACKNOWLEDGED;
else if (this.writeConcern.equals("UNACKNOWLEDGED"))
return WriteConcern.UNACKNOWLEDGED;
else if (this.writeConcern.equals("FSYNCED"))
return WriteConcern.FSYNCED;
else if (this.writeConcern.equals("JOURNALED"))
return WriteConcern.JOURNALED;
else if (this.writeConcern.equals("ERRORS_IGNORED"))
return WriteConcern.UNACKNOWLEDGED;
throw new RuntimeException("未知的WriteConcern:" + writeConcern);
}
private ReadPreference _getReadPreference() {
if (StringUtil.isEmpty(this.readPreference))
return null;
if (readPreference.equals("PRIMARY"))
return ReadPreference.primary();
else if (readPreference.equals("SECONDARY"))
return ReadPreference.secondary();
else if (readPreference.equals("SECONDARY_PREFERRED"))
return ReadPreference.secondaryPreferred();
else if (readPreference.equals("PRIMARY_PREFERRED"))
return ReadPreference.primaryPreferred();
else if (readPreference.equals("NEAREST"))
return ReadPreference.nearest();
throw new RuntimeException("未知的ReadPreference:" + readPreference);
}
private void buildCredentials() {
if (this.credentials != null && this.credentials.size() > 0) {
this.mongoCredentials = new ArrayList<MongoCredential>();
for (ClientMongoCredential clientMongoCredential : this.credentials) {
if (StringUtil.isEmpty(clientMongoCredential.getMechanism())) {
mongoCredentials.add(MongoCredential.createCredential(clientMongoCredential.getUserName(),
clientMongoCredential.getDatabase(),
clientMongoCredential.getPassword().toCharArray()));
}
else if (clientMongoCredential.getMechanism().equals(MongoCredential.SCRAM_SHA_1_MECHANISM)) {
mongoCredentials.add(MongoCredential.createScramSha1Credential(clientMongoCredential.getUserName(),
clientMongoCredential.getDatabase(),
clientMongoCredential.getPassword().toCharArray()));
}
else if (clientMongoCredential.getMechanism().equals(MongoCredential.MONGODB_CR_MECHANISM)) {
mongoCredentials.add(MongoCredential.createMongoCRCredential(clientMongoCredential.getUserName(),
clientMongoCredential.getDatabase(), clientMongoCredential.getPassword().toCharArray()));
} else if (clientMongoCredential.getMechanism().equals(MongoCredential.PLAIN_MECHANISM)) {
mongoCredentials.add(MongoCredential.createPlainCredential(clientMongoCredential.getUserName(),
clientMongoCredential.getDatabase(), clientMongoCredential.getPassword().toCharArray()));
} else if (clientMongoCredential.getMechanism().equals(MongoCredential.MONGODB_X509_MECHANISM)) {
mongoCredentials
.add(MongoCredential.createMongoX509Credential(clientMongoCredential.getUserName()));
} else if (clientMongoCredential.getMechanism().equals(MongoCredential.GSSAPI_MECHANISM)) {
mongoCredentials.add(MongoCredential.createGSSAPICredential(clientMongoCredential.getUserName()));
}
}
}
}
public void init() {
try {
buildCredentials();
if (mode != null && mode.equals("simple")) {
this.initsimple();
} else {
// options.autoConnectRetry = autoConnectRetry;
// options.connectionsPerHost = connectionsPerHost;
// options.maxWaitTime = maxWaitTime;
// options.socketTimeout = socketTimeout;
// options.connectTimeout = connectTimeout;
// options.threadsAllowedToBlockForConnectionMultiplier =
// threadsAllowedToBlockForConnectionMultiplier;
// options.socketKeepAlive=socketKeepAlive;
Builder builder = MongoClientOptions.builder();
// builder.autoConnectRetry( autoConnectRetry);
_autoConnectRetry(builder, autoConnectRetry);
builder.connectionsPerHost(connectionsPerHost);
builder.maxWaitTime(maxWaitTime);
builder.socketTimeout(socketTimeout);
builder.connectTimeout(connectTimeout);
builder.threadsAllowedToBlockForConnectionMultiplier(threadsAllowedToBlockForConnectionMultiplier);
builder.socketKeepAlive(socketKeepAlive);
MongoClientOptions options = builder.build();// new
// MongoClientOptions();
MongoClient mongoClient = null;
List<ServerAddress> servers = parserAddress();
if (mongoCredentials == null || mongoCredentials.size() == 0) {
if (servers.size() > 1)
mongoClient = new MongoClient(servers, options);
else
mongoClient = new MongoClient(servers.get(0), options);
} else {
if (servers.size() > 1)
mongoClient = new MongoClient(servers, mongoCredentials, options);
else
mongoClient = new MongoClient(servers.get(0), mongoCredentials, options);
}
int[] ops = parserOption();
for (int i = 0; ops != null && i < ops.length; i++)
mongoClient.addOption(ops[i]);
WriteConcern wc = this._getWriteConcern();
if (wc != null)
mongoClient.setWriteConcern(wc);
// ReadPreference.secondaryPreferred();
// if(servers.size() > 1)
{
ReadPreference rf = _getReadPreference();
if (rf != null)
mongoClient.setReadPreference(ReadPreference.nearest());
}
// mongoClient.setReadPreference(ReadPreference.primaryPreferred());
this.mongoclient = mongoClient;
}
} catch (RuntimeException e) {
log.error("初始化mongodb client failed.", e);
throw e;
} catch (Exception e) {
log.error("初始化mongodb client failed.", e);
throw new RuntimeException(e);
}
}
private void _autoConnectRetry(Builder builder, boolean autoConnectRetry) {
if (autoConnectRetryMethod != null)
try {
autoConnectRetryMethod.invoke(builder, autoConnectRetry);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void initsimple() throws Exception {
try {
// MongoOptions options = new MongoOptions();
// options.autoConnectRetry = autoConnectRetry;
// options.connectionsPerHost = connectionsPerHost;
// options.maxWaitTime = maxWaitTime;
// options.socketTimeout = socketTimeout;
// options.connectTimeout = connectTimeout;
// options.threadsAllowedToBlockForConnectionMultiplier =
// threadsAllowedToBlockForConnectionMultiplier;
// options.socketKeepAlive=socketKeepAlive;
// Mongo mongoClient = new Mongo(parserAddress().get(0),options);
Builder builder = MongoClientOptions.builder();
// builder.autoConnectRetry( autoConnectRetry);
_autoConnectRetry(builder, autoConnectRetry);
builder.connectionsPerHost(connectionsPerHost);
builder.maxWaitTime(maxWaitTime);
builder.socketTimeout(socketTimeout);
builder.connectTimeout(connectTimeout);
builder.threadsAllowedToBlockForConnectionMultiplier(threadsAllowedToBlockForConnectionMultiplier);
builder.socketKeepAlive(socketKeepAlive);
MongoClientOptions options = builder.build();// new
// MongoClientOptions();
MongoClient mongoClient = null;
if (mongoCredentials == null || mongoCredentials.size() == 0) {
mongoClient = new MongoClient(parserAddress().get(0), options);
} else {
mongoClient = new MongoClient(parserAddress().get(0), mongoCredentials, options);
}
int[] ops = parserOption();
for (int i = 0; ops != null && i < ops.length; i++)
mongoClient.addOption(ops[i]);
WriteConcern wc = this._getWriteConcern();
if (wc != null)
mongoClient.setWriteConcern(wc);
// ReadPreference.secondaryPreferred();
// mongoClient.setReadPreference(ReadPreference.primaryPreferred());
this.mongoclient = mongoClient;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw e;
}
}
public void close() {
if (this.mongoclient != null)
this.mongoclient.close();
}
public static WriteResult update(DBCollection collection, DBObject q, DBObject o) {
try {
WriteResult wr = collection.update(q, o);
return wr;
} catch (WriteConcernException e) {
log.debug("update:", e);
return null;
}
}
public static WriteResult update(DBCollection collection, DBObject q, DBObject o, WriteConcern concern) {
WriteResult wr = collection.update(q, o, false, false, concern);
return wr;
}
public static DBObject findAndModify(DBCollection collection, DBObject query, DBObject update) {
try {
DBObject object = collection.findAndModify(query, update);
return object;
} catch (WriteConcernException e) {
log.debug("findAndModify:", e);
return null;
}
}
public static DBObject findAndRemove(DBCollection collection, DBObject query) {
try {
DBObject object = collection.findAndRemove(query);
return object;
} catch (WriteConcernException e) {
log.debug("findAndRemove:", e);
return null;
}
}
public static WriteResult insert(DBCollection collection, DBObject... arr) {
try {
return collection.insert(arr);
} catch (WriteConcernException e) {
log.debug("insert:", e);
return null;
}
}
public static WriteResult insert(DBCollection collection, List<? extends DBObject> arr) {
try {
return collection.insert(arr);
} catch (WriteConcernException e) {
log.debug("insert:", e);
return null;
}
}
public static WriteResult insert(WriteConcern concern, DBCollection collection, DBObject... arr) {
return collection.insert(arr, concern);
}
public static WriteResult insert(WriteConcern concern, DBCollection collection, List<? extends DBObject> arr) {
return collection.insert(arr, concern);
}
public static WriteResult remove(DBCollection collection, DBObject o) {
try {
return collection.remove(o);
} catch (WriteConcernException e) {
log.debug("remove:", e);
return null;
}
}
public static WriteResult remove(DBCollection collection, DBObject o, WriteConcern concern) {
return collection.remove(o, concern);
}
public DB getDB(String dbname) {
return this.mongoclient.getDB(dbname);
}
public DBCollection getDBCollection(String dbname,String table)
{
DB db = this.getDB(dbname);
return db.getCollection(table);
}
}