// created on 6/21/2004 // Npgsql.NpgsqlConnecionString.cs // // Author: // Glen Parker (glenebob@nwlink.com) // Veerapuram Varadhan (vvaradhan@novell.com) // // Copyright (C) 2002 The Npgsql Development Team // npgsql-general@gborg.postgresql.org // http://gborg.postgresql.org/project/npgsql/projdisplay.php // // Copyright (C) 2009 Novell Inc // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA using System; using System.Collections; using System.Collections.Specialized; using System.Text; using System.Resources; namespace Npgsql { /// /// Represents a connection string. /// internal sealed class NpgsqlConnectionString : IEnumerable { // Logging related values private static readonly String CLASSNAME = "NpgsqlConnectionString"; private static System.Resources.ResourceManager resman; private String connection_string = null; private ListDictionary connection_string_values; static NpgsqlConnectionString() { resman = new System.Resources.ResourceManager(typeof(NpgsqlConnectionString)); } private NpgsqlConnectionString(NpgsqlConnectionString Other) { connection_string = Other.connection_string; connection_string_values = new ListDictionary(CaseInsensitiveComparer.Default); foreach (DictionaryEntry DE in Other.connection_string_values) { connection_string_values.Add(DE.Key, DE.Value); } } private NpgsqlConnectionString(ListDictionary Values) { connection_string_values = Values; } /// /// Return an exact copy of this NpgsqlConnectionString. /// public NpgsqlConnectionString Clone() { return new NpgsqlConnectionString(this); } IEnumerator IEnumerable.GetEnumerator() { return connection_string_values.GetEnumerator(); } /// /// This method parses a connection string and returns a new NpgsqlConnectionString object. /// public static NpgsqlConnectionString ParseConnectionString(String CS) { ListDictionary new_values = new ListDictionary(CaseInsensitiveComparer.Default); String[] pairs; String[] keyvalue; if (CS == null) CS = String.Empty; // Get the key-value pairs delimited by ; pairs = CS.Split(';'); // Now, for each pair, get its key=value. foreach(String sraw in pairs) { String s = sraw.Trim(); String Key = "", Value = ""; // Just ignore these. if (s == "") { continue; } // Split this chunk on the first CONN_ASSIGN only. keyvalue = s.Split(new Char[] {'='}, 2); // Keys always get trimmed and uppercased. Key = keyvalue[0].Trim().ToUpper(); // Make sure the key is even there... if (Key.Length == 0) { throw new ArgumentException(resman.GetString("Exception_WrongKeyVal"), ""); } // We don't expect keys this long, and it might be about to be put // in an error message, so makes sure it is a sane length. if (Key.Length > 20) { Key = Key.Substring(0, 20); } // Check if there is a key-value pair. if (keyvalue.Length != 2) { throw new ArgumentException(resman.GetString("Exception_WrongKeyVal"), Key); } // Values always get trimmed. Value = keyvalue[1].Trim(); // Substitute the real key name if this is an alias key (ODBC stuff for example)... String AliasKey = (string)ConnectionStringKeys.Aliases[Key]; if (AliasKey != null) { Key = AliasKey; } // Add the pair to the dictionary.. new_values.Add(Key, Value); } return new NpgsqlConnectionString(new_values); } /// /// Case insensative accessor for indivual connection string values. /// public String this[String Key] { get { return (String)connection_string_values[Key]; } set { connection_string_values[Key] = value; connection_string = null; } } /// /// Report whether a value with the provided key name exists in this connection string. /// public Boolean Contains(String Key) { return connection_string_values.Contains(Key); } /// /// Return a clean string representation of this connection string. /// public override String ToString() { if (connection_string == null) { StringBuilder S = new StringBuilder(); foreach (DictionaryEntry DE in this) { S.AppendFormat("{0}={1};", DE.Key, DE.Value); } connection_string = S.ToString(); } return connection_string; } /// /// Return a string value from the current connection string, even if the /// given key is not in the string or if the value is null. /// public String ToString(String Key) { return ToString(Key, ""); } /// /// Return a string value from the current connection string, even if the /// given key is not in the string or if the value is null. /// public String ToString(String Key, String Default) { if (! connection_string_values.Contains(Key)) { return Default; } return Convert.ToString(connection_string_values[Key]); } /// /// Return an integer value from the current connection string, even if the /// given key is not in the string or if the value is null. /// Throw an appropriate exception if the value cannot be coerced to an integer. /// public Int32 ToInt32(String Key) { return ToInt32(Key, 0); } /// /// Return an integer value from the current connection string, even if the /// given key is not in the string or if the value is null. /// Throw an appropriate exception if the value cannot be coerced to an integer. /// public Int32 ToInt32(String Key, Int32 Min, Int32 Max) { return ToInt32(Key, Min, Max, 0); } /// /// Return an integer value from the current connection string, even if the /// given key is not in the string or if the value is null. /// Throw an appropriate exception if the value cannot be coerced to an integer. /// public Int32 ToInt32(String Key, Int32 Default) { if (! connection_string_values.Contains(Key)) { return Default; } try { return Convert.ToInt32(connection_string_values[Key]); } catch (Exception E) { throw new ArgumentException(String.Format(resman.GetString("Exception_InvalidIntegerKeyVal"), Key), Key, E); } } /// /// Return an integer value from the current connection string, even if the /// given key is not in the string. /// Throw an appropriate exception if the value cannot be coerced to an integer. /// public Int32 ToInt32(String Key, Int32 Min, Int32 Max, Int32 Default) { Int32 V; V = ToInt32(Key, Default); if (V < Min) { throw new ArgumentException(String.Format(resman.GetString("Exception_IntegerKeyValMin"), Key, Min), Key); } if (V > Max) { throw new ArgumentException(String.Format(resman.GetString("Exception_IntegerKeyValMax"), Key, Max), Key); } return V; } /// /// Return a boolean value from the current connection string, even if the /// given key is not in the string. /// Throw an appropriate exception if the value is not recognized as a boolean. /// public Boolean ToBool(String Key) { return ToBool(Key, false); } /// /// Return a boolean value from the current connection string, even if the /// given key is not in the string. /// Throw an appropriate exception if the value is not recognized as a boolean. /// public Boolean ToBool(String Key, Boolean Default) { if (! connection_string_values.Contains(Key)) { return Default; } switch (connection_string_values[Key].ToString().ToLower()) { case "t" : case "true" : case "y" : case "yes" : return true; case "f" : case "false" : case "n" : case "no" : return false; default : throw new ArgumentException(String.Format(resman.GetString("Exception_InvalidBooleanKeyVal"), Key), Key); } } /// /// Return a ProtocolVersion from the current connection string, even if the /// given key is not in the string. /// Throw an appropriate exception if the value is not recognized as /// integer 2 or 3. /// public ProtocolVersion ToProtocolVersion(String Key) { if (! connection_string_values.Contains(Key)) { return ProtocolVersion.Version3; } switch (ToInt32(Key)) { case 2 : return ProtocolVersion.Version2; case 3 : return ProtocolVersion.Version3; default : throw new ArgumentException(String.Format(resman.GetString("Exception_InvalidProtocolVersionKeyVal"), Key), Key); } } public SslMode ToSslMode(String Key) { return ToSslMode(Key, SslMode.Disable); } /// /// public SslMode ToSslMode(String Key, SslMode Default) { if (! connection_string_values.Contains(Key)) { return Default; } return (SslMode)Enum.Parse(typeof(SslMode), ToString(Key), true); } } /// /// Know connection string keys. /// internal abstract class ConnectionStringKeys { public static readonly String Host = "SERVER"; public static readonly String Port = "PORT"; public static readonly String Protocol = "PROTOCOL"; public static readonly String Database = "DATABASE"; public static readonly String UserName = "USER ID"; public static readonly String Password = "PASSWORD"; public static readonly String SSL = "SSL"; public static readonly String SslMode = "SSLMODE"; public static readonly String Encoding = "ENCODING"; public static readonly String Timeout = "TIMEOUT"; // These are for the connection pool public static readonly String Pooling = "POOLING"; public static readonly String ConnectionLifeTime = "CONNECTIONLIFETIME"; public static readonly String MinPoolSize = "MINPOOLSIZE"; public static readonly String MaxPoolSize = "MAXPOOLSIZE"; public static readonly String SyncNotification = "SYNCNOTIFICATION"; // These are for the command public static readonly String CommandTimeout = "COMMANDTIMEOUT"; // A list of aliases for some of the above values. If one of these aliases is // encountered when parsing a connection string, it's real key name will // be used instead. These will be reflected if ToString() is used to inspect // the string. private static ListDictionary _aliases; static ConnectionStringKeys() { _aliases = new ListDictionary(); // Aliases to help catch common errors. _aliases.Add("DB", Database); _aliases.Add("HOST", Host); _aliases.Add("USER", UserName); _aliases.Add("USERID", UserName); _aliases.Add("USER NAME", UserName); _aliases.Add("USERNAME", UserName); _aliases.Add("PSW", Password); // Aliases to make migration from ODBC easier. _aliases.Add("UID", UserName); _aliases.Add("PWD", Password); } public static IDictionary Aliases { get { return _aliases; } } } /// /// Connection string default values. /// internal abstract class ConnectionStringDefaults { // Connection string defaults public static readonly Int32 Port = 5432; public static readonly String Encoding = "SQL_ASCII"; public static readonly Boolean Pooling = true; public static readonly Int32 MinPoolSize = 1; public static readonly Int32 MaxPoolSize = 20; public static readonly Int32 Timeout = 15; // Seconds public static readonly Int32 ConnectionLifeTime = 15; // Seconds public static readonly Boolean SyncNotification = false; public static readonly Int32 CommandTimeout = 20; // Seconds } /* internal enum SslMode { Disable = 1 << 0, Allow = 1 << 1, Prefer = 1 << 2, Require = 1 << 3 } */ }