MongoDB Java Driver 源码分析(5):com.mongodb.DB

DB 表示数据库连接,是一个抽象类,部分核心功能由子类提供,由 DBApiLayer 继承。

[align=center][size=medium][b]由子类实现的抽象方法[/b][/size][/align]
[code]
// 开始数据库连接
public abstract void requestStart();
// 结束数据库连接
public abstract void requestDone();
// 保持数据库连接
public abstract void requestEnsureConnection();

// 获取指定名称的数据集
protected abstract DBCollection doGetCollection( String name );
[/code]

[align=center][size=medium][b]数据集相关的方法[/b][/size][/align]
[code]
// 创建数据集
public final DBCollection createCollection( String name, DBObject options ){
// 如果 options 不为空
// 则先以 options 构造创建数据库的命令
// 然后执行创建数据库的命令并得到结果
if ( options != null ){
DBObject createCmd = new BasicDBObject("create", name);
createCmd.putAll(options);
CommandResult result = command(createCmd);
result.throwOnError();
}

return getCollection(name);
}

// 解析用 "." 分隔的字符串,获取指定的数据集
public DBCollection getCollectionFromString( String s ){
DBCollection foo = null;

// 获取 "." 所在位置
int idx = s.indexOf( "." );

// 当分解后的字符串中仍然包含 "." 时
// 循环分解字符串,知道所有 "." 号解析完毕
// 效果类似于递归调用,但这里采用了循环的写法
while ( idx >= 0 ){
// 获取 "." 之前的字符串 b
String b = s.substring( 0 , idx );
// 获取 "." 之后的字符串 s
s = s.substring( idx + 1 );

// 检查上次解析得到的对象 foo 是否为空
if ( foo == null )
foo = getCollection( b );
else
foo = foo.getCollection( b );

// 获取 "." 所在位置
idx = s.indexOf( "." );
}

if ( foo != null )
return foo.getCollection( s );

return getCollection( s );
}

// 获取所有数据集名称
public Set<String> getCollectionNames()
throws MongoException {

// 获取系统的 namespace 数据集
DBCollection namespaces = getCollection("system.namespaces");
if (namespaces == null)
throw new RuntimeException("this is impossible");

// 获取用于遍历 namespace 的迭代器
Iterator<DBObject> i = namespaces.__find(new BasicDBObject(), null, 0, 0, 0, getOptions());
if (i == null)
return new HashSet<String>();

// 表名称 List,最后转换为 set 并返回
List<String> tables = new ArrayList<String>();

for (; i.hasNext();) {
DBObject o = i.next();
if ( o.get( "name" ) == null ){
throw new MongoException( "how is name null : " + o );
}

// 获取 namespace 名称
String n = o.get("name").toString();

// 获取 namespace 名称前缀
int idx = n.indexOf(".");
String root = n.substring(0, idx);

// 如果前缀不为当前 DB 的名称
// 表示这个 namespace 不属于当前 DB
if (!root.equals(_name))
continue;

// 忽略特殊数据集
if (n.indexOf("$") >= 0)
continue;

// 获取数据集名称
String table = n.substring(idx + 1);

tables.add(table);
}

Collections.sort(tables);

// 转换为 Set
return new LinkedHashSet<String>(tables);
}
[/code]

[align=center][size=medium][b]数据库命令相关的方法[/b][/size][/align]
[code]
// 执行数据库命令
public CommandResult command( DBObject cmd , int options )
throws MongoException {

// 调用 DBCollection 的 find 方法
Iterator<DBObject> i = getCollection("$cmd").__find(cmd, new BasicDBObject(), 0, -1, 0, options);
if ( i == null || ! i.hasNext() )
return null;

// 获得数据库命令的返回结果结果
CommandResult res = (CommandResult)i.next();
res._cmd = cmd;
return res;
}

// 以 "eval" 方式解析命令
public CommandResult doEval( String code , Object ... args )
throws MongoException {

// 构造 "eval" 命令
// 调用 command 方法执行并获得结果
return command( BasicDBObjectBuilder.start()
.add( "$eval" , code )
.add( "args" , args )
.get() );
}

// 删除数据库
public void dropDatabase()
throws MongoException {

CommandResult res = command(new BasicDBObject("dropDatabase", 1));
res.throwOnError();
_mongo._dbs.remove(this.getName());
}
[/code]

[align=center][size=medium][b]用户相关的方法[/b][/size][/align]
[code]
// 验证用户名和密码
public CommandResult authenticateCommand(String username, char[] passwd )
throws MongoException {

if ( username == null || passwd == null )
throw new NullPointerException( "username can't be null" );

if ( _username != null )
throw new IllegalStateException( "can't call authenticate twice on the same DBObject" );

// 根据用户名和密码,通过 MD5 计算哈希值
String hash = _hash( username , passwd );

// 验证用户名和密码并获得返回结果
CommandResult res = _doauth( username , hash.getBytes() );
res.throwOnError();
_username = username;
_authhash = hash.getBytes();
return res;
}

// 验证用户名和密码并获得返回结果
private CommandResult _doauth( String username , byte[] hash ){
// 获取 "盐值",用于加密
CommandResult res = command(new BasicDBObject("getnonce", 1), getOptions());
res.throwOnError();

// 利用当前的用户名和密码,执行一个没有实际意义的操作
// 利用 username, 加密后的密码,以及盐值进行验证,看看是否产生错误
DBObject cmd = _authCommand( res.getString( "nonce" ) , username , hash );
return command(cmd, getOptions());
}


// 利用 username, 加密后的密码,以及盐值进行验证,看看是否产生错误
static DBObject _authCommand( String nonce , String username , byte[] hash ){
// 获取由 username, 加密后的密码,以及盐值 组成的 key
String key = nonce + username + new String( hash );

// 构造用于验证用户的命令
BasicDBObject cmd = new BasicDBObject();

cmd.put("authenticate", 1);
cmd.put("user", username);
cmd.put("nonce", nonce);

// 对 key 进行 MD5 加密
cmd.put("key", Util.hexMD5(key.getBytes()));

return cmd;
}

// 添加用户
public WriteResult addUser( String username , char[] passwd, boolean readOnly ){
// 获取系统用户
DBCollection c = getCollection( "system.users" );

// 根据指定的 username 获取用户
DBObject o = c.findOne( new BasicDBObject( "user" , username ) );
// 如果不存在,则创建
if ( o == null )
o = new BasicDBObject( "user" , username );

// 设置密码
o.put( "pwd" , _hash( username , passwd ) );
// 设置只读权限
o.put( "readOnly" , readOnly );

// 将构造出来的用户对象添加到 系统用户数据集 中
return c.save( o );
}

// 删除用户
public WriteResult removeUser( String username ){
DBCollection c = getCollection( "system.users" );
return c.remove(new BasicDBObject( "user" , username ));
}
[/code]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值