diff options
author | Matt Cotter <matt.cotter@mongodb.com> | 2016-07-13 14:39:35 -0400 |
---|---|---|
committer | Matt Cotter <matt.cotter@mongodb.com> | 2016-08-18 14:13:01 -0400 |
commit | 88b540f0c14c7ab8af708aecc4cd6df83081b32e (patch) | |
tree | a6f01563ac2b8db7d34f98e5fab3d17f5416e315 /src/mongo/scripting | |
parent | ceeb17e4265c4c48765acbf9ad6a60b5f1889332 (diff) | |
download | mongo-88b540f0c14c7ab8af708aecc4cd6df83081b32e.tar.gz |
SERVER-22382 allow mongo --host to take uri
Diffstat (limited to 'src/mongo/scripting')
-rw-r--r-- | src/mongo/scripting/SConscript | 5 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/implscope.cpp | 10 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/implscope.h | 13 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/internedstring.defs | 8 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/mongo.cpp | 8 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/objectwrapper.cpp | 7 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/objectwrapper.h | 1 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/uri.cpp | 105 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/uri.h | 52 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/valuereader.cpp | 34 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/valuereader.h | 1 |
11 files changed, 216 insertions, 28 deletions
diff --git a/src/mongo/scripting/SConscript b/src/mongo/scripting/SConscript index fc32d46d01a..8c2604c76b6 100644 --- a/src/mongo/scripting/SConscript +++ b/src/mongo/scripting/SConscript @@ -107,8 +107,8 @@ if usemozjs: 'mozjs/countdownlatch.cpp', 'mozjs/cursor.cpp', 'mozjs/cursor_handle.cpp', - 'mozjs/dbcollection.cpp', 'mozjs/db.cpp', + 'mozjs/dbcollection.cpp', 'mozjs/dbpointer.cpp', 'mozjs/dbquery.cpp', 'mozjs/dbref.cpp', @@ -128,9 +128,9 @@ if usemozjs: 'mozjs/mongohelpers.cpp', 'mozjs/mongohelpers_js.cpp', 'mozjs/nativefunction.cpp', + 'mozjs/numberdecimal.cpp', 'mozjs/numberint.cpp', 'mozjs/numberlong.cpp', - 'mozjs/numberdecimal.cpp', 'mozjs/object.cpp', 'mozjs/objectwrapper.cpp', 'mozjs/oid.cpp', @@ -138,6 +138,7 @@ if usemozjs: 'mozjs/proxyscope.cpp', 'mozjs/regexp.cpp', 'mozjs/timestamp.cpp', + 'mozjs/uri.cpp', 'mozjs/valuereader.cpp', 'mozjs/valuewriter.cpp', ], diff --git a/src/mongo/scripting/mozjs/implscope.cpp b/src/mongo/scripting/mozjs/implscope.cpp index 2b01e99454b..fff5f233ac2 100644 --- a/src/mongo/scripting/mozjs/implscope.cpp +++ b/src/mongo/scripting/mozjs/implscope.cpp @@ -336,12 +336,12 @@ MozJSImplScope::MozJSImplScope(MozJSScriptEngine* engine) _bsonProto(_context), _codeProto(_context), _countDownLatchProto(_context), - _cursorProto(_context), _cursorHandleProto(_context), + _cursorProto(_context), _dbCollectionProto(_context), + _dbProto(_context), _dbPointerProto(_context), _dbQueryProto(_context), - _dbProto(_context), _dbRefProto(_context), _errorProto(_context), _jsThreadProto(_context), @@ -351,13 +351,14 @@ MozJSImplScope::MozJSImplScope(MozJSScriptEngine* engine) _mongoHelpersProto(_context), _mongoLocalProto(_context), _nativeFunctionProto(_context), + _numberDecimalProto(_context), _numberIntProto(_context), _numberLongProto(_context), - _numberDecimalProto(_context), _objectProto(_context), _oidProto(_context), _regExpProto(_context), - _timestampProto(_context) { + _timestampProto(_context), + _uriProto(_context) { kCurrentScope = this; // The default is quite low and doesn't seem to directly correlate with @@ -790,6 +791,7 @@ void MozJSImplScope::installBSONTypes() { _oidProto.install(_global); _regExpProto.install(_global); _timestampProto.install(_global); + _uriProto.install(_global); // This builtin map is a javascript 6 thing. We want our version. so // take theirs out diff --git a/src/mongo/scripting/mozjs/implscope.h b/src/mongo/scripting/mozjs/implscope.h index d8225bffdde..080716428ac 100644 --- a/src/mongo/scripting/mozjs/implscope.h +++ b/src/mongo/scripting/mozjs/implscope.h @@ -60,6 +60,7 @@ #include "mongo/scripting/mozjs/oid.h" #include "mongo/scripting/mozjs/regexp.h" #include "mongo/scripting/mozjs/timestamp.h" +#include "mongo/scripting/mozjs/uri.h" namespace mongo { namespace mozjs { @@ -289,6 +290,11 @@ public: return _timestampProto; } + template <typename T> + typename std::enable_if<std::is_same<T, URIInfo>::value, WrapType<T>&>::type getProto() { + return _uriProto; + } + void setQuickExit(int exitCode); bool getQuickExit(int* exitCode); @@ -380,12 +386,12 @@ private: WrapType<BSONInfo> _bsonProto; WrapType<CodeInfo> _codeProto; WrapType<CountDownLatchInfo> _countDownLatchProto; - WrapType<CursorInfo> _cursorProto; WrapType<CursorHandleInfo> _cursorHandleProto; + WrapType<CursorInfo> _cursorProto; WrapType<DBCollectionInfo> _dbCollectionProto; + WrapType<DBInfo> _dbProto; WrapType<DBPointerInfo> _dbPointerProto; WrapType<DBQueryInfo> _dbQueryProto; - WrapType<DBInfo> _dbProto; WrapType<DBRefInfo> _dbRefProto; WrapType<ErrorInfo> _errorProto; WrapType<JSThreadInfo> _jsThreadProto; @@ -395,13 +401,14 @@ private: WrapType<MongoHelpersInfo> _mongoHelpersProto; WrapType<MongoLocalInfo> _mongoLocalProto; WrapType<NativeFunctionInfo> _nativeFunctionProto; + WrapType<NumberDecimalInfo> _numberDecimalProto; WrapType<NumberIntInfo> _numberIntProto; WrapType<NumberLongInfo> _numberLongProto; - WrapType<NumberDecimalInfo> _numberDecimalProto; WrapType<ObjectInfo> _objectProto; WrapType<OIDInfo> _oidProto; WrapType<RegExpInfo> _regExpProto; WrapType<TimestampInfo> _timestampProto; + WrapType<URIInfo> _uriProto; }; inline MozJSImplScope* getScope(JSContext* cx) { diff --git a/src/mongo/scripting/mozjs/internedstring.defs b/src/mongo/scripting/mozjs/internedstring.defs index 792ec0bbcb5..fe2394edb27 100644 --- a/src/mongo/scripting/mozjs/internedstring.defs +++ b/src/mongo/scripting/mozjs/internedstring.defs @@ -53,3 +53,11 @@ MONGO_MOZJS_INTERNED_STRING(str, "str") MONGO_MOZJS_INTERNED_STRING(top, "top") MONGO_MOZJS_INTERNED_STRING(t, "t") MONGO_MOZJS_INTERNED_STRING(type, "type") +MONGO_MOZJS_INTERNED_STRING(uri, "uri") +MONGO_MOZJS_INTERNED_STRING(user, "user") +MONGO_MOZJS_INTERNED_STRING(password, "password") +MONGO_MOZJS_INTERNED_STRING(options, "options") +MONGO_MOZJS_INTERNED_STRING(database, "database") +MONGO_MOZJS_INTERNED_STRING(isValid, "isValid") +MONGO_MOZJS_INTERNED_STRING(setName, "setName") +MONGO_MOZJS_INTERNED_STRING(servers, "servers") diff --git a/src/mongo/scripting/mozjs/mongo.cpp b/src/mongo/scripting/mozjs/mongo.cpp index b7d9677fd0a..da62b092f34 100644 --- a/src/mongo/scripting/mozjs/mongo.cpp +++ b/src/mongo/scripting/mozjs/mongo.cpp @@ -638,8 +638,7 @@ void MongoExternalInfo::construct(JSContext* cx, JS::CallArgs args) { } auto statusWithHost = MongoURI::parse(host); - uassertStatusOK(statusWithHost); - auto cs = statusWithHost.getValue(); + auto cs = uassertStatusOK(statusWithHost); std::string errmsg; std::unique_ptr<DBClientBase> conn(cs.connect("MongoDB Shell", errmsg)); @@ -657,8 +656,9 @@ void MongoExternalInfo::construct(JSContext* cx, JS::CallArgs args) { JS_SetPrivate(thisv, new std::shared_ptr<DBClientBase>(conn.release())); o.setBoolean(InternedString::slaveOk, false); - o.setString(InternedString::host, host); - o.setString(InternedString::defaultDB, cs.getDatabase()); + o.setString(InternedString::host, cs.toString()); + auto defaultDB = cs.getDatabase() == "" ? "test" : cs.getDatabase(); + o.setString(InternedString::defaultDB, defaultDB); args.rval().setObjectOrNull(thisv); } diff --git a/src/mongo/scripting/mozjs/objectwrapper.cpp b/src/mongo/scripting/mozjs/objectwrapper.cpp index 5c921c1ebec..98f8094dfcc 100644 --- a/src/mongo/scripting/mozjs/objectwrapper.cpp +++ b/src/mongo/scripting/mozjs/objectwrapper.cpp @@ -361,6 +361,13 @@ void ObjectWrapper::setBSON(Key key, const BSONObj& obj, bool readOnly) { setValue(key, value); } +void ObjectWrapper::setBSONArray(Key key, const BSONObj& obj, bool readOnly) { + JS::RootedValue value(_context); + ValueReader(_context, &value).fromBSONArray(obj, nullptr, readOnly); + + setValue(key, value); +} + void ObjectWrapper::setValue(Key key, JS::HandleValue val) { key.set(_context, _object, val); } diff --git a/src/mongo/scripting/mozjs/objectwrapper.h b/src/mongo/scripting/mozjs/objectwrapper.h index 8c85a5b42d1..cf6c61d39e1 100644 --- a/src/mongo/scripting/mozjs/objectwrapper.h +++ b/src/mongo/scripting/mozjs/objectwrapper.h @@ -115,6 +115,7 @@ public: void setBoolean(Key key, bool val); void setBSONElement(Key key, const BSONElement& elem, const BSONObj& obj, bool readOnly); void setBSON(Key key, const BSONObj& obj, bool readOnly); + void setBSONArray(Key key, const BSONObj& obj, bool readOnly); void setValue(Key key, JS::HandleValue value); void setObject(Key key, JS::HandleObject value); diff --git a/src/mongo/scripting/mozjs/uri.cpp b/src/mongo/scripting/mozjs/uri.cpp new file mode 100644 index 00000000000..f943bb8a171 --- /dev/null +++ b/src/mongo/scripting/mozjs/uri.cpp @@ -0,0 +1,105 @@ +/** + * Copyright (C) 2016 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#include "mongo/platform/basic.h" + +#include "mongo/scripting/mozjs/uri.h" + +#include <algorithm> +#include <iterator> + +#include "mongo/client/mongo_uri.h" +#include "mongo/scripting/mozjs/implscope.h" +#include "mongo/scripting/mozjs/objectwrapper.h" +#include "mongo/scripting/mozjs/valuereader.h" +#include "mongo/scripting/mozjs/valuewriter.h" +#include "mongo/scripting/mozjs/wrapconstrainedmethod.h" +#include "mongo/stdx/memory.h" +#include "mongo/util/mongoutils/str.h" + +namespace mongo { +namespace mozjs { + +const JSFunctionSpec URIInfo::methods[2] = { + MONGO_ATTACH_JS_CONSTRAINED_METHOD(toString, URIInfo), JS_FS_END, +}; + +const char* const URIInfo::className = "MongoURI"; + +void URIInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) { + ObjectWrapper o(cx, args.thisv()); + ValueReader(cx, args.rval()).fromStringData(o.getString(InternedString::uri)); +} + +void URIInfo::construct(JSContext* cx, JS::CallArgs args) { + uassert(ErrorCodes::BadValue, "MongoURI needs 1 argument", args.length() == 1); + + JS::HandleValue uriArg = args.get(0); + if (!uriArg.isString()) + uasserted(ErrorCodes::BadValue, "uri must be a string"); + + std::string uri = ValueWriter(cx, args.get(0)).toString(); + + auto sw = MongoURI::parse(uri); + auto parsed = uassertStatusOK(sw); + + BSONArrayBuilder serversBuilder; + for (const auto hp : parsed.getServers()) { + BSONObjBuilder b; + b.append("server", hp.toString()); + b.append("host", hp.host()); + if (hp.hasPort()) { + b.append("port", hp.port()); + } + serversBuilder.append(b.obj()); + } + + BSONObjBuilder optsBuilder; + for (const auto& kvpair : parsed.getOptions()) { + optsBuilder.append(kvpair.first, kvpair.second); + } + + JS::RootedObject thisv(cx); + auto scope = getScope(cx); + scope->getProto<URIInfo>().newObject(&thisv); + ObjectWrapper o(cx, thisv); + + o.setValue(InternedString::uri, uriArg); + o.setString(InternedString::user, parsed.getUser()); + o.setString(InternedString::password, parsed.getPassword()); + o.setBSON(InternedString::options, optsBuilder.obj(), true); + o.setString(InternedString::database, parsed.getDatabase()); + o.setBoolean(InternedString::isValid, parsed.isValid()); + o.setString(InternedString::setName, parsed.getSetName()); + o.setBSONArray(InternedString::servers, serversBuilder.arr(), true); + + args.rval().setObjectOrNull(thisv); +} + +} // namespace mozjs +} // namespace mongo diff --git a/src/mongo/scripting/mozjs/uri.h b/src/mongo/scripting/mozjs/uri.h new file mode 100644 index 00000000000..d1b487ce2ab --- /dev/null +++ b/src/mongo/scripting/mozjs/uri.h @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2016 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#pragma once + +#include "mongo/scripting/mozjs/wraptype.h" + +namespace mongo { +namespace mozjs { + +/** + * A MongoURI object. + */ +struct URIInfo : public BaseInfo { + static void construct(JSContext* cx, JS::CallArgs args); + + struct Functions { + MONGO_DECLARE_JS_FUNCTION(toString); + }; + + static const JSFunctionSpec methods[2]; + + static const char* const className; +}; + +} // namespace mozjs +} // namespace mongo diff --git a/src/mongo/scripting/mozjs/valuereader.cpp b/src/mongo/scripting/mozjs/valuereader.cpp index af26238763d..1eedef58e86 100644 --- a/src/mongo/scripting/mozjs/valuereader.cpp +++ b/src/mongo/scripting/mozjs/valuereader.cpp @@ -97,21 +97,7 @@ void ValueReader::fromBSONElement(const BSONElement& elem, const BSONObj& parent _value.setInt32(elem.Int()); return; case mongo::Array: { - JS::AutoValueVector avv(_context); - - BSONForEach(subElem, elem.embeddedObject()) { - JS::RootedValue member(_context); - - ValueReader(_context, &member).fromBSONElement(subElem, parent, readOnly); - if (!avv.append(member)) { - uasserted(ErrorCodes::JSInterpreterFailure, "Failed to append to JS array"); - } - } - JS::RootedObject array(_context, JS_NewArrayObject(_context, avv)); - if (!array) { - uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_NewArrayObject"); - } - _value.setObjectOrNull(array); + fromBSONArray(elem.embeddedObject(), &parent, readOnly); return; } case mongo::Object: @@ -254,6 +240,24 @@ void ValueReader::fromBSON(const BSONObj& obj, const BSONObj* parent, bool readO _value.setObjectOrNull(child); } +void ValueReader::fromBSONArray(const BSONObj& obj, const BSONObj* parent, bool readOnly) { + JS::AutoValueVector avv(_context); + + BSONForEach(elem, obj) { + JS::RootedValue member(_context); + + ValueReader(_context, &member).fromBSONElement(elem, parent ? *parent : obj, readOnly); + if (!avv.append(member)) { + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to append to JS array"); + } + } + JS::RootedObject array(_context, JS_NewArrayObject(_context, avv)); + if (!array) { + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_NewArrayObject"); + } + _value.setObjectOrNull(array); +} + /** * SpiderMonkey doesn't have a direct entry point to create a jsstring from * utf8, so we have to flow through some slightly less public interfaces. diff --git a/src/mongo/scripting/mozjs/valuereader.h b/src/mongo/scripting/mozjs/valuereader.h index 6b03d30086c..58abed86c45 100644 --- a/src/mongo/scripting/mozjs/valuereader.h +++ b/src/mongo/scripting/mozjs/valuereader.h @@ -49,6 +49,7 @@ public: void fromBSONElement(const BSONElement& elem, const BSONObj& parent, bool readOnly); void fromBSON(const BSONObj& obj, const BSONObj* parent, bool readOnly); + void fromBSONArray(const BSONObj& obj, const BSONObj* parent, bool readOnly); void fromDouble(double d); void fromStringData(StringData sd); void fromDecimal128(Decimal128 decimal); |