Merge pull request #2006 from steffen-kiess/posix-sockets-2
[mono.git] / mcs / class / System.Data / Mainsoft.Data.Configuration.jvm / KeyMapperBase.cs
1 //
2 // System.Data.OleDb.OleDbConnection
3 //
4 // Authors:
5 //      Konstantin Triger <kostat@mainsoft.com>
6 //      Boris Kirzner <borisk@mainsoft.com>
7 //      
8 // (C) 2006 Mainsoft Corporation (http://www.mainsoft.com)
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System;
33 using System.Collections;
34 using System.Collections.Specialized;
35 using System.Text;
36 using System.Globalization;
37 using System.IO;
38
39 namespace Mainsoft.Data.Configuration
40 {
41         public class ConnectionStringDictionary: IConnectionStringDictionary
42         {
43                 #region Fields
44
45                 private readonly IDictionary _dictionary;
46                 private readonly NameValueCollection _mapping;
47                 private readonly NameValueCollection _actualKeys;
48                 const string DataDirectoryPlaceholder = "|DataDirectory|";
49
50                 #endregion // Fields
51
52                 #region Constructors
53
54                 public ConnectionStringDictionary(string connectionString, NameValueCollection defaultMapping)
55                 {
56                         _actualKeys = new NameValueCollection(StringComparer.OrdinalIgnoreCase);
57                         _dictionary = Parse (connectionString);
58                         _mapping = defaultMapping;
59                 }
60
61                 #endregion // Constructors
62
63                 #region Methods
64
65                 public string GetConnectionStringKey (string key)
66                 {
67                         string cached = _actualKeys [key];
68                         if (cached != null)
69                                 return cached;
70
71                         if (_mapping != null)
72                         for(int i = 0, c = _mapping.Keys.Count; i < c; i++) {
73                                 if (string.Compare(key, _mapping.Keys[i], StringComparison.OrdinalIgnoreCase) == 0) {
74                                         string[] values = _mapping.GetValues(i);
75                                         for(int j = 0; j < values.Length; j++) {
76                                                 string actualKey = values[j];
77                                                 if (_dictionary.Contains (actualKey)) {
78                                                         _actualKeys.Add (key, actualKey);
79                                                         return actualKey;
80                                                 }
81                                         }
82                                 }
83                         }
84
85                         if (_dictionary.Contains(key))
86                                 return key;
87
88                         return null;
89                 }
90
91                 public object GetValue (string key)
92                 {
93                         return _dictionary [key];
94                 }
95
96                 public static IDictionary Parse (string connectionString)
97                 {
98                         IDictionary userParameters = new Hashtable (StringComparer.OrdinalIgnoreCase);
99
100                         if (connectionString == null || connectionString.Length == 0) {
101                                 return userParameters;
102                         }
103                         //connectionString += ";";
104
105                         if (connectionString.IndexOf (DataDirectoryPlaceholder, StringComparison.Ordinal) >= 0) {
106                                 string dataDirectory = (string) AppDomain.CurrentDomain.GetData ("DataDirectory");
107                                 if (dataDirectory != null && dataDirectory.Length > 0) {
108                                         char lastChar = dataDirectory [dataDirectory.Length - 1];
109                                         if (lastChar != Path.DirectorySeparatorChar &&
110                                                 lastChar != Path.AltDirectorySeparatorChar)
111                                                 dataDirectory += '/';
112                                 }
113                                 connectionString = connectionString.Replace (DataDirectoryPlaceholder, dataDirectory);
114                         }
115
116                         bool inQuote = false;
117                         bool inDQuote = false;
118                         bool inName = true;
119
120                         string name = String.Empty;
121                         string value = String.Empty;
122                         StringBuilder sb = new StringBuilder (connectionString.Length);
123
124                         for (int i = 0; i < connectionString.Length; i ++) {
125                                 char c = connectionString [i];
126                                 char peek;
127                                 if (i == connectionString.Length - 1)
128                                         peek = '\0';
129                                 else
130                                         peek = connectionString [i + 1];
131
132                                 switch (c) {
133                                         case '\'':
134                                                 if (inDQuote)
135                                                         sb.Append (c);
136                                                 else if (peek == c) {
137                                                         sb.Append(c);
138                                                         i ++;
139                                                 }
140                                                 else
141                                                         inQuote = !inQuote;
142                                                 break;
143                                         case '"':
144                                                 if (inQuote)
145                                                         sb.Append(c);
146                                                 else if (peek == c) {
147                                                         sb.Append(c);
148                                                         i ++;
149                                                 }
150                                                 else
151                                                         inDQuote = !inDQuote;
152                                                 break;
153                                         case ';':
154                                                 if (inDQuote || inQuote)
155                                                         sb.Append(c);
156                                                 else {
157                                                         if (name != null && name.Length > 0) {
158                                                                 value = sb.ToString();
159                                                                 userParameters [name.Trim()] = value.Trim();
160                                                         }
161                                                         inName = true;
162                                                         name = String.Empty;
163                                                         value = String.Empty;
164                                                         sb.Length = 0;
165                                                 }
166                                                 break;
167                                         case '=':
168                                                 if (inDQuote || inQuote || !inName)
169                                                         sb.Append (c);
170                                                 else if (peek == c) {
171                                                         sb.Append (c);
172                                                         i += 1;
173                                                 }
174                                                 else {
175                                                         name = sb.ToString();
176                                                         sb.Length = 0;
177                                                         inName = false;
178                                                 }
179                                                 break;
180                                         case ' ':
181                                                 if (inQuote || inDQuote)
182                                                         sb.Append(c);
183                                                 else if (sb.Length > 0 && peek != ';')
184                                                         sb.Append(c);
185                                                 break;
186                                         default:
187                                                 sb.Append(c);
188                                                 break;
189                                 }
190                         }
191
192                         if (inDQuote || inQuote)
193                                 throw new ArgumentException("connectionString");
194
195                         if (name != null && name.Length > 0) {
196                                 value = sb.ToString();
197                                 userParameters [name.Trim()] = value.Trim();
198                         }
199
200                         return userParameters;
201                 }
202
203
204                 #endregion // Methods
205
206                 #region IDictionary Members
207
208                 public virtual bool IsFixedSize
209                 {
210                         get { return _dictionary.IsFixedSize; }
211                 }
212
213                 public virtual bool IsReadOnly
214                 {
215                         get { return _dictionary.IsReadOnly; }
216                 }
217
218                 public virtual ICollection Keys
219                 {
220                         get { 
221                                 return _dictionary.Keys; 
222                         }
223                 }
224
225                 public virtual object this [object key] {
226                         get { 
227
228                                 if (!(key is String))
229                                         throw new ArgumentException("key is not string");
230
231                                 string skey = (string)key;
232
233                                 skey = GetConnectionStringKey(skey);
234                                 if (skey == null)
235                                         return null;
236
237                                 return _dictionary[skey];
238                         }
239
240                         set {
241                                 if (!(key is String))
242                                         throw new ArgumentException("key is not string");
243
244                                 string skey = (string)key;
245
246                                 skey = GetConnectionStringKey(skey);
247                                 if (skey == null)
248                                         skey = (string)key;
249
250                                 _dictionary[skey] = value;
251                         }
252                 }
253
254                 public virtual ICollection Values
255                 {
256                         get { return _dictionary.Values; }
257                 }
258
259                 public virtual void Add (object key, object value)
260                 {
261                         _dictionary.Add ((string)key, (string)value);
262                 }
263
264                 public virtual void Clear ()
265                 {
266                         _dictionary.Clear ();
267                 }
268
269                 public virtual bool Contains (object key)
270                 {
271                         return _dictionary.Contains (key);
272                 }
273
274                 public virtual IDictionaryEnumerator GetEnumerator ()
275                 {
276                         return _dictionary.GetEnumerator ();
277                 }
278
279                 public virtual void Remove (object key)
280                 {
281                         _dictionary.Remove ((string)key);
282                 }
283
284                 #endregion // IDictionary Members
285
286                 #region IEnumerable Members
287
288                 IEnumerator IEnumerable.GetEnumerator () 
289                 {
290                         return this.GetEnumerator();
291                 }
292
293                 #endregion // IEnumerable Members
294
295                 #region ICollection Members
296
297                 public virtual bool IsSynchronized 
298                 {
299                         get { return ((ICollection)_dictionary).IsSynchronized; }
300                 }
301
302                 public virtual int Count 
303                 {
304                         get { return _dictionary.Count; }
305                 }
306
307                 public virtual void CopyTo (Array array, int index) 
308                 {
309                         _dictionary.CopyTo (array, index);
310                 }
311
312                 public virtual object SyncRoot 
313                 {
314                         get {return ((ICollection)_dictionary).SyncRoot; }
315                 }
316
317                 #endregion // ICollection Members
318         }
319 }