// constructors
 /// <summary>
 /// Creates a new instance of MongoUrlBuilder.
 /// </summary>
 public MongoUrlBuilder()
 {
     _authenticationProtocol = MongoAuthenticationProtocol.Strongest;
     _authenticationSource = null;
     _connectionMode = ConnectionMode.Automatic;
     _connectTimeout = MongoDefaults.ConnectTimeout;
     _databaseName = null;
     _fsync = null;
     _guidRepresentation = MongoDefaults.GuidRepresentation;
     _ipv6 = false;
     _journal = null;
     _maxConnectionIdleTime = MongoDefaults.MaxConnectionIdleTime;
     _maxConnectionLifeTime = MongoDefaults.MaxConnectionLifeTime;
     _maxConnectionPoolSize = MongoDefaults.MaxConnectionPoolSize;
     _minConnectionPoolSize = MongoDefaults.MinConnectionPoolSize;
     _password = null;
     _readPreference = null;
     _replicaSetName = null;
     _secondaryAcceptableLatency = MongoDefaults.SecondaryAcceptableLatency;
     _servers = null;
     _slaveOk = null;
     _socketTimeout = MongoDefaults.SocketTimeout;
     _username = null;
     _useSsl = false;
     _verifySslCertificate = true;
     _w = null;
     _waitQueueMultiple = MongoDefaults.WaitQueueMultiple;
     _waitQueueSize = MongoDefaults.WaitQueueSize;
     _waitQueueTimeout = MongoDefaults.WaitQueueTimeout;
     _wTimeout = null;
 }
        public void TestAuthProtocol(MongoAuthenticationProtocol authProtocol, string connectionString)
        {
            var built = new MongoUrlBuilder { Server = _localhost, AuthenticationProtocol = authProtocol };

            foreach (var builder in EnumerateBuiltAndParsedBuilders(built, connectionString))
            {
                Assert.AreEqual(authProtocol, builder.AuthenticationProtocol);
                Assert.AreEqual(connectionString, builder.ToString());
            }
        }
        /// <summary>
        /// Parses a URL and sets all settings to match the URL.
        /// </summary>
        /// <param name="url">The URL.</param>
        public void Parse(string url)
        {
            const string serverPattern = @"((\[[^]]+?\]|[^:,/?#]+)(:\d+)?)";
            const string pattern =
                @"^mongodb://" +
                @"((?<username>[^:]+)(:(?<password>.*?))?@)?" +
                @"(?<servers>" + serverPattern + @"(," + serverPattern + ")*)?" +
                @"(/(?<database>[^?]+)?(\?(?<query>.*))?)?$";
            Match match = Regex.Match(url, pattern);
            if (match.Success)
            {
                var usernameGroup = match.Groups["username"];
                if (usernameGroup.Success)
                {
                    _username = Uri.UnescapeDataString(usernameGroup.Value);
                }
                var passwordGroup = match.Groups["password"];
                if (passwordGroup.Success)
                {
                    _password = Uri.UnescapeDataString(passwordGroup.Value);
                }
                string servers = match.Groups["servers"].Value;
                var databaseGroup = match.Groups["database"];
                if (databaseGroup.Success)
                {
                    _databaseName = databaseGroup.Value;
                }
                string query = match.Groups["query"].Value;

                if (servers != "")
                {
                    List<MongoServerAddress> addresses = new List<MongoServerAddress>();
                    foreach (string server in servers.Split(','))
                    {
                        var address = MongoServerAddress.Parse(server);
                        addresses.Add(address);
                    }
                    _servers = addresses;
                }

                if (!string.IsNullOrEmpty(query))
                {
                    foreach (var pair in query.Split('&', ';'))
                    {
                        var parts = pair.Split('=');
                        if (parts.Length != 2)
                        {
                            throw new FormatException(string.Format("Invalid connection string '{0}'.", parts));
                        }
                        var name = parts[0];
                        var value = parts[1];

                        switch (name.ToLower())
                        {
                            case "authprotocol":
                                _authenticationProtocol = ParseAuthenticationProtocol(name, value);
                                break;
                            case "authsource":
                                _authenticationSource = value;
                                break;
                            case "connect":
                                ConnectionMode = ParseConnectionMode(name, value);
                                break;
                            case "connecttimeout":
                            case "connecttimeoutms":
                                ConnectTimeout = ParseTimeSpan(name, value);
                                break;
                            case "fsync":
                                FSync = ParseBoolean(name, value);
                                break;
                            case "guids":
                            case "uuidrepresentation":
                                GuidRepresentation = (GuidRepresentation)Enum.Parse(typeof(GuidRepresentation), value, true); // ignoreCase
                                break;
                            case "ipv6":
                                IPv6 = ParseBoolean(name, value);
                                break;
                            case "j":
                            case "journal":
                                Journal = ParseBoolean(name, value);
                                break;
                            case "maxidletime":
                            case "maxidletimems":
                                MaxConnectionIdleTime = ParseTimeSpan(name, value);
                                break;
                            case "maxlifetime":
                            case "maxlifetimems":
                                MaxConnectionLifeTime = ParseTimeSpan(name, value);
                                break;
                            case "maxpoolsize":
                                MaxConnectionPoolSize = ParseInt32(name, value);
                                break;
                            case "minpoolsize":
                                MinConnectionPoolSize = ParseInt32(name, value);
                                break;
                            case "readpreference":
                                if (_readPreference == null) { _readPreference = new ReadPreference(); }
                                ReadPreference.ReadPreferenceMode = ParseReadPreferenceMode(name, value);
                                break;
                            case "readpreferencetags":
                                if (_readPreference == null) { _readPreference = new ReadPreference { ReadPreferenceMode = ReadPreferenceMode.Primary }; }
                                ReadPreference.AddTagSet(ParseReplicaSetTagSet(name, value));
                                break;
                            case "replicaset":
                                ReplicaSetName = value;
                                break;
                            case "safe":
                                var safe = Convert.ToBoolean(value);
                                if (_w == null)
                                {
                                    W = safe ? 1 : 0;
                                }
                                else
                                {
                                    if (safe)
                                    {
                                        // don't overwrite existing W value unless it's 0
                                        var wCount = _w as WriteConcern.WCount;
                                        if (wCount != null && wCount.Value == 0)
                                        {
                                            W = 1;
                                        }
                                    }
                                    else
                                    {
                                        W = 0;
                                    }
                                }
                                break;
                            case "secondaryacceptablelatency":
                            case "secondaryacceptablelatencyms":
                                SecondaryAcceptableLatency = ParseTimeSpan(name, value);
                                break;
                            case "slaveok":
#pragma warning disable 618
                                SlaveOk = ParseBoolean(name, value);
#pragma warning restore
                                break;
                            case "sockettimeout":
                            case "sockettimeoutms":
                                SocketTimeout = ParseTimeSpan(name, value);
                                break;
                            case "ssl":
                                UseSsl = ParseBoolean(name, value);
                                break;
                            case "sslverifycertificate":
                                VerifySslCertificate = ParseBoolean(name, value);
                                break;
                            case "w":
                                W = WriteConcern.WValue.Parse(value);
                                break;
                            case "waitqueuemultiple":
                                WaitQueueMultiple = ParseDouble(name, value);
                                break;
                            case "waitqueuesize":
                                WaitQueueSize = ParseInt32(name, value);
                                break;
                            case "waitqueuetimeout":
                            case "waitqueuetimeoutms":
                                WaitQueueTimeout = ParseTimeSpan(name, value);
                                break;
                            case "wtimeout":
                            case "wtimeoutms":
                                WTimeout = ParseTimeSpan(name, value);
                                break;
                            default:
                                var message = string.Format("Invalid option '{0}'.", name);
                                throw new ArgumentException(message, "url");
                        }
                    }
                }
            }
            else
            {
                throw new FormatException(string.Format("Invalid connection string '{0}'.", url));
            }
        }