merging the Mainsoft branch to the trunk
[mono.git] / mcs / class / System.Data / System.Data.ProviderBase.jvm / AbstractDBConnection.cs
1 //\r
2 // System.Data.Common.AbstractDBConnection\r
3 //\r
4 // Author:\r
5 //   Boris Kirzner (borisk@mainsoft.com)\r
6 //\r
7 \r
8 using System.Data;\r
9 using System.Data.ProviderBase;\r
10 using System.Data.Configuration;\r
11 using System.Configuration;\r
12 using System.Collections;\r
13 using System.Collections.Specialized;\r
14 using System.Text;\r
15 using System.Text.RegularExpressions;\r
16 \r
17 using java.sql;\r
18 using javax.sql;\r
19 using javax.naming;\r
20 // can not use java.util here - it manes ArrayList an ambiguous reference\r
21 \r
22 namespace System.Data.Common\r
23 {\r
24         public abstract class AbstractDBConnection : DbConnection\r
25         {\r
26                 #region ObjectNamesHelper\r
27 \r
28                 private sealed class ObjectNamesHelper\r
29                 {\r
30                         //static readonly Regex NameOrder = new Regex(@"^\s*((\[(?<NAME>(\s*[^\[\]\s])+)\s*\])|(?<NAME>(\w|!|\#|\$)+(\s*(\w|!|\#|\$)+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
31                         static readonly Regex NameOrder = new Regex(@"^((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
32 \r
33                         //static readonly Regex SchemaNameOrder = new Regex(@"^\s*((\[(?<SCHEMA>(\s*[^\[\]\s])+)\s*\])|(?<SCHEMA>(\w|!|\#|\$)*(\s*(\w|!|\#|\$)+)*))\s*\.\s*((\[(?<NAME>(\s*[^\[\]\s])+)\s*\])|(?<NAME>(\w|!|\#|\$)+(\s*(\w|!|\#|\$)+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
34                         static readonly Regex SchemaNameOrder = new Regex(@"^((\[(?<SCHEMA>[^\]]+)\])|(?<SCHEMA>[^\.\[\]]+))\s*\.\s*((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
35                         //static readonly Regex CatalogSchemaNameOrder = new Regex(@"^\s*((\[\s*(?<CATALOG>(\s*[^\[\]\s])+)\s*\])|(?<CATALOG>(\w|!|\#|\$)*(\s*(\w|!|\#|\$)+)*))\s*\.\s*((\[(?<SCHEMA>(\s*[^\[\]\s])+)\s*\])|(?<SCHEMA>(\w|!|\#|\$)*(\s*(\w|!|\#|\$)+)*))\s*\.\s*((\[(?<NAME>(\s*[^\[\]\s])+)\s*\])|(?<NAME>(\w|!|\#|\$)+(\s*(\w|!|\#|\$)+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
36                         //static readonly Regex CatalogSchemaNameOrder = new Regex(@"^\s*((\[\s*(?<CATALOG>(\s*[^\]\s])+)\s*\])|(?<CATALOG>([^\.\s])*(\s*([^\.\s])+)*))\s*\.\s*((\[(?<SCHEMA>(\s*[^\]\s])+)\s*\])|(?<SCHEMA>([^\.\s])*(\s*([^\.\s])+)*))\s*\.\s*((\[(?<NAME>(\s*[^\]\s])+)\s*\])|(?<NAME>([^\.\s])+(\s*([^\.\s])+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
37                         static readonly Regex CatalogSchemaNameOrder = new Regex(@"^((\[(?<CATALOG>[^\]]+)\])|(?<CATALOG>[^\.\[\]]+))\s*\.\s*((\[(?<SCHEMA>[^\]]+)\])|(?<SCHEMA>[^\.\[\]]+))\s*\.\s*((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
38 \r
39                         //static readonly Regex CatalogNameOrder = new Regex(@"^\s*((\[(?<CATALOG>(\s*[^\[\]\s])+)\s*\])|(?<CATALOG>(\w|!|\#|\$)*(\s*(\w|!|\#|\$)+)*))\s*\.\s*((\[(?<NAME>(\s*[^\[\]\s])+)\s*\])|(?<NAME>(\w|!|\#|\$)+(\s*(\w|!|\#|\$)+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
40                         //static readonly Regex CatalogNameOrder = new Regex(@"^\s*((\[(?<CATALOG>(\s*[^\]\s])+)\s*\])|(?<CATALOG>([^\.\s])*(\s*([^\.\s])+)*))\s*\.\s*((\[(?<NAME>(\s*[^\]\s])+)\s*\])|(?<NAME>([^\.\s])+(\s*([^\.\s])+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
41                         static readonly Regex CatalogNameOrder = new Regex(@"^((\[(?<CATALOG>[^\]]+)\])|(?<CATALOG>[^\.\[\]]+))\s*\.\s*((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
42                         //static readonly Regex SchemaCatalogNameOrder = new Regex(@"^\s*((\[\s*(?<SCHEMA>(\s*[^\[\]\s])+)\s*\])|(?<SCHEMA>(\w|!|\#|\$)*(\s*(\w|!|\#|\$)+)*))\s*\.\s*((\[(?<CATALOG>(\s*[^\[\]\s])+)\s*\])|(?<CATALOG>(\w|!|\#|\$)*(\s*(\w|!|\#|\$)+)*))\s*\.\s*((\[(?<NAME>(\s*[^\[\]\s])+)\s*\])|(?<NAME>(\w|!|\#|\$)+(\s*(\w|!|\#|\$)+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
43                         //static readonly Regex SchemaCatalogNameOrder = new Regex(@"^\s*((\[\s*(?<SCHEMA>(\s*[^\]\s])+)\s*\])|(?<SCHEMA>([^\.\s])*(\s*([^\.\s])+)*))\s*\.\s*((\[(?<CATALOG>(\s*[^\]\s])+)\s*\])|(?<CATALOG>([^\.\s])*(\s*([^\.\s])+)*))\s*\.\s*((\[(?<NAME>(\s*[^\]\s])+)\s*\])|(?<NAME>([^\.\s])+(\s*([^\.\s])+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
44                         static readonly Regex SchemaCatalogNameOrder = new Regex(@"^((\[(?<SCHEMA>[^\]]+)\])|(?<SCHEMA>[^\.\[\]]+))\s*\.\s*((\[(?<CATALOG>[^\]]+)\])|(?<CATALOG>[^\.\[\]]+))\s*\.\s*((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
45 \r
46                         internal static ObjectNameResolver[] GetSyntaxPatterns(AbstractDBConnection connection)\r
47                         {\r
48                                 ArrayList collection = new ArrayList();\r
49                                 collection.Add(new ObjectNameResolver(NameOrder));\r
50 \r
51                                 ObjectNameResolversCollection basic = (ObjectNameResolversCollection)ConfigurationSettings.GetConfig("system.data/objectnameresolution");\r
52                                 \r
53                                 DatabaseMetaData metaData = connection.JdbcConnection.getMetaData();\r
54                                 string productName = metaData.getDatabaseProductName();\r
55 \r
56                                 foreach(ObjectNameResolver nameResolver in basic) {\r
57                                         if (productName.IndexOf(nameResolver.DbName) != -1) {\r
58                                                 collection.Add(nameResolver);\r
59                                         }\r
60                                 }\r
61 \r
62                                 //defaults\r
63                                 if (metaData.isCatalogAtStart()) {\r
64                                         collection.Add(new ObjectNameResolver(SchemaNameOrder));\r
65                                         collection.Add(new ObjectNameResolver(CatalogNameOrder));\r
66                                         collection.Add(new ObjectNameResolver(CatalogSchemaNameOrder));\r
67                                         collection.Add(new ObjectNameResolver(SchemaCatalogNameOrder));\r
68                                 }\r
69                                 else {\r
70                                         collection.Add(new ObjectNameResolver(CatalogNameOrder));\r
71                                         collection.Add(new ObjectNameResolver(SchemaNameOrder));\r
72                                         collection.Add(new ObjectNameResolver(SchemaCatalogNameOrder));\r
73                                         collection.Add(new ObjectNameResolver(CatalogSchemaNameOrder));\r
74                                 }\r
75 \r
76                                 return (ObjectNameResolver[])collection.ToArray(typeof(ObjectNameResolver));                            \r
77                         }\r
78                 }\r
79 \r
80                 #endregion // ObjectNamesHelper\r
81 \r
82                 #region ConnectionStringHelper\r
83 \r
84                 internal sealed class ConnectionStringHelper\r
85                 {\r
86                         internal static string FindValue(NameValueCollection collection, string[] keys)\r
87                         {\r
88                                 if (collection == null || keys == null || keys.Length == 0) {\r
89                                         return String.Empty;\r
90                                 }\r
91 \r
92                                 for(int i=0; i < keys.Length; i++) {\r
93                                         string value = FindValue(collection,keys[i]);\r
94                                         if (!String.Empty.Equals(value)) {\r
95                                                 return value;\r
96                                         }\r
97                                 }\r
98                                 return String.Empty;\r
99                         }\r
100 \r
101                         internal static string FindValue(NameValueCollection collection, string key)\r
102                         {\r
103                                 if (collection == null) {\r
104                                         return String.Empty;\r
105                                 }\r
106 \r
107                                 string value = collection[key];\r
108                                 return (value != null) ? value : String.Empty;\r
109                         }\r
110 \r
111                         internal static void UpdateValue(NameValueCollection collection,string[] keys,string value)\r
112                         {\r
113                                 for(int i=0; i < keys.Length; i++) {\r
114                                         if (collection[keys[i]] != null) {\r
115                                                 collection[keys[i]] = value;\r
116                                         }\r
117                                 }\r
118                         }\r
119 \r
120                         internal static void AddValue(NameValueCollection collection,string[] keys,string value)\r
121                         {\r
122                                 for(int i=0; i < keys.Length; i++) {\r
123                                         collection[keys[i]] = value;\r
124                                 }\r
125                         }\r
126 \r
127                         /**\r
128                         * Parses connection string and builds NameValueCollection \r
129                         * for all keys.\r
130                         */ \r
131                         internal static NameValueCollection BuildUserParameters (string connectionString)\r
132                         {\r
133                                 NameValueCollection userParameters = new NameValueCollection();\r
134 \r
135                                 if (connectionString == null || connectionString.Length == 0) {\r
136                                         return userParameters;\r
137                                 }\r
138                                 connectionString += ";";\r
139 \r
140                                 bool inQuote = false;\r
141                                 bool inDQuote = false;\r
142                                 bool inName = true;\r
143 \r
144                                 string name = String.Empty;\r
145                                 string value = String.Empty;\r
146                                 StringBuilder sb = new StringBuilder ();\r
147 \r
148                                 for (int i = 0; i < connectionString.Length; i += 1) {\r
149                                         char c = connectionString [i];\r
150                                         char peek;\r
151                                         if (i == connectionString.Length - 1)\r
152                                                 peek = '\0';\r
153                                         else\r
154                                                 peek = connectionString [i + 1];\r
155 \r
156                                         switch (c) {\r
157                                                 case '\'':\r
158                                                         if (inDQuote)\r
159                                                                 sb.Append (c);\r
160                                                         else if (peek.Equals(c)) {\r
161                                                                 sb.Append(c);\r
162                                                                 i += 1;\r
163                                                         }\r
164                                                         else\r
165                                                                 inQuote = !inQuote;\r
166                                                         break;\r
167                                                 case '"':\r
168                                                         if (inQuote)\r
169                                                                 sb.Append(c);\r
170                                                         else if (peek.Equals(c)) {\r
171                                                                 sb.Append(c);\r
172                                                                 i += 1;\r
173                                                         }\r
174                                                         else\r
175                                                                 inDQuote = !inDQuote;\r
176                                                         break;\r
177                                                 case ';':\r
178                                                         if (inDQuote || inQuote)\r
179                                                                 sb.Append(c);\r
180                                                         else {\r
181                                                                 if (name != String.Empty && name != null) {\r
182                                                                         value = sb.ToString();\r
183                                                                         userParameters [name.Trim()] = value.Trim();\r
184                                                                 }\r
185                                                                 inName = true;\r
186                                                                 name = String.Empty;\r
187                                                                 value = String.Empty;\r
188                                                                 sb = new StringBuilder();\r
189                                                         }\r
190                                                         break;\r
191                                                 case '=':\r
192                                                         if (inDQuote || inQuote || !inName)\r
193                                                                 sb.Append (c);\r
194                                                         else if (peek.Equals(c)) {\r
195                                                                 sb.Append (c);\r
196                                                                 i += 1;\r
197                                                         }\r
198                                                         else {\r
199                                                                 name = sb.ToString();\r
200                                                                 sb = new StringBuilder();\r
201                                                                 inName = false;\r
202                                                         }\r
203                                                         break;\r
204                                                 case ' ':\r
205                                                         if (inQuote || inDQuote)\r
206                                                                 sb.Append(c);\r
207                                                         else if (sb.Length > 0 && !peek.Equals(';'))\r
208                                                                 sb.Append(c);\r
209                                                         break;\r
210                                                 default:\r
211                                                         sb.Append(c);\r
212                                                         break;\r
213                                         }\r
214                                 }\r
215                                 return userParameters;\r
216                         }\r
217                 }\r
218 \r
219                 #endregion // ConnectionStringHelper\r
220 \r
221                 #region DataSourceCache\r
222 \r
223                 private sealed class DataSourceCache : AbstractDbMetaDataCache\r
224                 {\r
225                         internal DataSource GetDataSource(string dataSourceName,string namingProviderUrl,string namingFactoryInitial)\r
226                         {\r
227                                 Hashtable cache = Cache;\r
228 \r
229                                 DataSource ds = cache[dataSourceName] as DataSource;\r
230 \r
231                                 if (ds != null) {\r
232                                         return ds;\r
233                                 }\r
234 \r
235                                 Context ctx = null;\r
236                                 \r
237                                 java.util.Properties properties = new java.util.Properties();\r
238 \r
239                                 if ((namingProviderUrl != null) && (namingProviderUrl.Length > 0)) {\r
240                                         properties.put("java.naming.provider.url",namingProviderUrl);\r
241                                 }\r
242                                 \r
243                                 if ((namingFactoryInitial != null) && (namingFactoryInitial.Length > 0)) {\r
244                                         properties.put("java.naming.factory.initial",namingFactoryInitial);\r
245                                 }\r
246 \r
247                                 ctx = new InitialContext(properties);\r
248  \r
249                                 try {\r
250                                         ds = (DataSource)ctx.lookup(dataSourceName);\r
251                                 }\r
252                                 catch(javax.naming.NameNotFoundException e) {\r
253                                         // possible that is a Tomcat bug,\r
254                                         // so try to lookup for jndi datasource with "java:comp/env/" appended\r
255                                         ds = (DataSource)ctx.lookup("java:comp/env/" + dataSourceName);\r
256                                 }\r
257 \r
258                                 cache[dataSourceName] = ds;\r
259                                 return ds;\r
260                         }\r
261                 }\r
262 \r
263                 #endregion // DatasourceCache\r
264 \r
265                 #region Declarations\r
266 \r
267                 protected internal enum JDBC_MODE { NONE, DATA_SOURCE_MODE, JDBC_DRIVER_MODE, PROVIDER_MODE }\r
268                 protected internal enum PROVIDER_TYPE { NONE, SQLOLEDB, MSDAORA, IBMDADB2 }\r
269 \r
270                 #endregion // Declarations\r
271                 \r
272                 #region Fields\r
273 \r
274                 private static DataSourceCache _dataSourceCache = new DataSourceCache();\r
275                 private const int DEFAULT_TIMEOUT = 15;\r
276 \r
277                 private Connection _jdbcConnnection;\r
278                 private ConnectionState _internalState;\r
279                 private object _internalStateSync = new object();\r
280 \r
281                 private NameValueCollection _userParameters;\r
282 \r
283                 protected string _connectionString = String.Empty;\r
284                 protected string _jdbcUrl;              \r
285 \r
286                 private ArrayList _referencedObjects = new ArrayList(); \r
287                 private ObjectNameResolver[] _syntaxPatterns;\r
288 \r
289                 #endregion // Fields\r
290 \r
291                 #region Constructors\r
292 \r
293                 public AbstractDBConnection(string connectionString)\r
294                 {\r
295                         _connectionString = connectionString;\r
296                         InitializeSkippedUserParameters();\r
297                 }\r
298 \r
299                 #endregion // Constructors\r
300 \r
301                 #region Properties\r
302 \r
303                 public override String ConnectionString\r
304                 {\r
305                         get { return _connectionString; }\r
306                         set {\r
307                                 if (IsOpened) {\r
308                                         throw ExceptionHelper.NotAllowedWhileConnectionOpen("ConnectionString",_internalState);\r
309                                 }                                       \r
310                                 _connectionString = value;\r
311                                 _userParameters = null;\r
312                                 _jdbcUrl = null;\r
313                         }\r
314                 }\r
315 \r
316                 public override int ConnectionTimeout\r
317                 {\r
318                         get {\r
319                                 string timeoutStr = ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_TIMEOUT"));\r
320                                 if (!String.Empty.Equals(timeoutStr)) {\r
321                                         try {\r
322                                                 return Convert.ToInt32(timeoutStr);\r
323                                         }\r
324                                         catch(FormatException e) {\r
325                                                 throw ExceptionHelper.InvalidValueForKey("connect timeout");\r
326                                         }\r
327                                         catch (OverflowException e) {\r
328                                                 throw ExceptionHelper.InvalidValueForKey("connect timeout");\r
329                                         }\r
330                                 }\r
331                                 return DEFAULT_TIMEOUT;\r
332                         }\r
333                 }\r
334 \r
335                 public override String Database\r
336                 {\r
337                         get { return ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_DATABASE")); }\r
338                 }\r
339 \r
340                 public override ConnectionState State\r
341                 {\r
342                         get {\r
343                                 try {\r
344                                         if ((JdbcConnection == null) || JdbcConnection.isClosed()) {\r
345                                                 // jdbc connection not initialized or closed\r
346                                                 if (_internalState == ConnectionState.Closed ) {\r
347                                                         return ConnectionState.Closed;\r
348                                                 }\r
349                                         }\r
350                                         else {\r
351                                                 // jdbc connection is opened\r
352                                                 if ((_internalState & ConnectionState.Open) != 0) {\r
353                                                         return ConnectionState.Open;\r
354                                                 }\r
355                                         }\r
356                                         return ConnectionState.Broken;                                                                          \r
357                                 }       \r
358                                 catch (SQLException) {\r
359                                         return ConnectionState.Broken;\r
360                                 }                               \r
361                         }\r
362                 }\r
363 \r
364                 internal bool IsExecuting\r
365                 {\r
366                         get { \r
367                                 return ((_internalState & ConnectionState.Executing) != 0);\r
368                         }\r
369 \r
370                         set {\r
371                                 lock(_internalStateSync) {\r
372                                         // to switch to executing, the connection must be in opened\r
373                                         if (value) {\r
374                                                 if (_internalState != ConnectionState.Open) {\r
375                                                         if (IsFetching) {\r
376                                                                 throw ExceptionHelper.OpenedReaderExists();\r
377                                                         }\r
378                                                         throw ExceptionHelper.OpenConnectionRequired("",_internalState);\r
379                                                 }\r
380                                                 _internalState |= ConnectionState.Executing;\r
381                                         }\r
382                                         else { \r
383                                                 if (!IsExecuting) {\r
384                                                         throw new InvalidOperationException("Connection : Impossible to tear down from state " + ConnectionState.Executing.ToString() + " while in state " + _internalState.ToString());\r
385                                                 }\r
386                                                 _internalState &= ~ConnectionState.Executing;\r
387                                         }\r
388                                 }\r
389                         }\r
390                 }\r
391 \r
392                 internal bool IsFetching\r
393                 {\r
394                         get {\r
395                                 return ((_internalState & ConnectionState.Fetching) != 0);\r
396                         }\r
397 \r
398                         set {\r
399                                 lock(_internalStateSync) {\r
400                                         if (value) {\r
401                                                 // to switch to fetching connection must be in opened, executing\r
402                                                 if (((_internalState & ConnectionState.Open) == 0) || ((_internalState & ConnectionState.Executing) == 0)) {\r
403                                                         throw ExceptionHelper.OpenConnectionRequired("",_internalState);\r
404                                                 }\r
405                                                 _internalState |= ConnectionState.Fetching;\r
406                                         }\r
407                                         else {\r
408                                                 if (!IsFetching) {\r
409                                                         throw new InvalidOperationException("Connection : Impossible to tear down from state " + ConnectionState.Fetching.ToString() + " while in state " + _internalState.ToString());\r
410                                                 }\r
411                                                 _internalState &= ~ConnectionState.Fetching;\r
412                                         }\r
413                                 }\r
414                         }\r
415                 }\r
416 \r
417                 internal bool IsOpened\r
418                 {\r
419                         get {\r
420                                 return ((_internalState & ConnectionState.Open) != 0);\r
421                         }\r
422 \r
423                         set {\r
424                                 lock(_internalStateSync) {                      \r
425                                         if (value) {\r
426                                                 // only connecting connection can be opened\r
427                                                 if ((_internalState != ConnectionState.Connecting)) {\r
428                                                         throw ExceptionHelper.ConnectionAlreadyOpen(_internalState);\r
429                                                 }\r
430                                                 _internalState |= ConnectionState.Open;\r
431                                         }\r
432                                         else {\r
433                                                 if (!IsOpened) {\r
434                                                         throw new InvalidOperationException("Connection : Impossible to tear down from state " + ConnectionState.Open.ToString() + " while in state " + _internalState.ToString());\r
435                                                 }\r
436                                                 _internalState &= ~ConnectionState.Open;\r
437                                         }\r
438                                 }\r
439                         }\r
440                 }\r
441 \r
442                 internal bool IsConnecting\r
443                 {\r
444                         get {\r
445                                 return ((_internalState & ConnectionState.Connecting) != 0);\r
446                         }\r
447 \r
448                         set {\r
449                                 lock(_internalStateSync) {                      \r
450                                         if (value) {\r
451                                                 // to switch to connecting conection must be in closed or in opened\r
452                                                 if ((_internalState != ConnectionState.Closed) && (_internalState != ConnectionState.Open)) {\r
453                                                         throw ExceptionHelper.ConnectionAlreadyOpen(_internalState);\r
454                                                 }\r
455                                                 _internalState |= ConnectionState.Connecting;\r
456                                         }\r
457                                         else {\r
458                                                 if (!IsConnecting) {\r
459                                                         throw new InvalidOperationException("Connection : Impossible to tear down from state " + ConnectionState.Connecting.ToString() + " while in state " + _internalState.ToString());\r
460                                                 }\r
461                                                 _internalState &= ~ConnectionState.Connecting;\r
462                                         }\r
463                                 }\r
464                         }\r
465                 }\r
466 \r
467                 protected virtual PROVIDER_TYPE ProviderType\r
468                 {\r
469                         get {\r
470                                 if (JdbcMode != JDBC_MODE.PROVIDER_MODE) {\r
471                                         return PROVIDER_TYPE.NONE;\r
472                                 }\r
473                                 \r
474                                 string providerStr = ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_PROVIDER"));\r
475                                 if (providerStr.StartsWith("SQLOLEDB")) {\r
476                                         return PROVIDER_TYPE.SQLOLEDB;\r
477                                 }\r
478                                 else if (providerStr.StartsWith("MSDAORA")) {\r
479                                         return PROVIDER_TYPE.MSDAORA;\r
480                                 }\r
481                                 else if (providerStr.StartsWith("IBMDADB2")) {\r
482                                         return PROVIDER_TYPE.IBMDADB2;\r
483                                 }\r
484                                 return PROVIDER_TYPE.NONE;\r
485                         }\r
486                 }\r
487 \r
488                 protected internal virtual JDBC_MODE JdbcMode\r
489                 {\r
490                         get { \r
491                                 string[] conJndiNameStr = StringManager.GetStringArray("CON_JNDI_NAME");\r
492                                 if ( !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,conJndiNameStr))) {\r
493                                         return JDBC_MODE.DATA_SOURCE_MODE;\r
494                                 }\r
495 \r
496                                 string[] jdbcDriverStr = StringManager.GetStringArray("JDBC_DRIVER");\r
497                                 string[] jdbcUrlStr = StringManager.GetStringArray("JDBC_URL");\r
498                                 bool jdbcDriverSpecified = !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,jdbcDriverStr));\r
499                                 bool jdbcUrlSpecified = !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,jdbcUrlStr));\r
500 \r
501                                 if (jdbcDriverSpecified && jdbcUrlSpecified) {\r
502                                         return JDBC_MODE.JDBC_DRIVER_MODE;\r
503                                 }\r
504 \r
505                                 string[] providerStr = StringManager.GetStringArray("CON_PROVIDER");\r
506                                 if (!String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,providerStr))) {\r
507                                         return JDBC_MODE.PROVIDER_MODE;\r
508                                 }\r
509                                 \r
510                                 return JDBC_MODE.NONE;\r
511                         }\r
512                 }\r
513 \r
514                 protected virtual string JdbcDriverName\r
515                 {\r
516                         get { return String.Empty; }\r
517                 }\r
518 \r
519                 protected abstract DbStringManager StringManager\r
520                 {\r
521                         get;\r
522                 }\r
523 \r
524                 protected virtual string ServerName\r
525                 {\r
526                         get { return DataSource; }\r
527                 }\r
528 \r
529                 protected virtual string CatalogName\r
530                 {\r
531                         get { return Database; }\r
532                 }\r
533 \r
534                 protected virtual string Port\r
535                 {\r
536                         get {\r
537                                 string port = ConnectionStringHelper.FindValue(UserParameters, StringManager.GetStringArray("CON_PORT"));\r
538                                 switch (ProviderType) {\r
539                                         case PROVIDER_TYPE.SQLOLEDB : \r
540                                                 if (String.Empty.Equals(port)) {\r
541                                                         // if needed - resolve MSSQL port\r
542                                                         // FIXME : decide about behaviour in the case all the timeout spent on port resolution\r
543                                                         //long start = DateTime.Now.Ticks;\r
544                                                         port = DbPortResolver.getMSSqlPort(DataSource,InstanceName,ConnectionTimeout).ToString();\r
545                                                         //long end = DateTime.Now.Ticks;                                                                                                        \r
546                                                         //if( (end - start) < ConnectionTimeout*1000000) {                                                              \r
547                                                                 //timeout -= (int)(end - start)/1000000;\r
548                                                         //}\r
549                                                 }\r
550                                                 // todo : what should we do if all the timeout spent on port resolution ?\r
551                                                 if ("-1".Equals(port)) {\r
552                                                         port = StringManager.GetString("SQL_CON_PORT", "1433"); //default port of MSSql Server 3167.\r
553                                                 }\r
554                                                 ConnectionStringHelper.AddValue(UserParameters,StringManager.GetStringArray("CON_PORT"),port);\r
555                                                 break;\r
556                                 }\r
557                                 return port;\r
558                         }\r
559                 }\r
560 \r
561                 public override string DataSource\r
562                 {\r
563                         get {\r
564                                 string dataSource = ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_DATA_SOURCE"));\r
565 \r
566                                 if (ProviderType == PROVIDER_TYPE.SQLOLEDB) {\r
567                                         int instanceIdx;\r
568                                         if ((instanceIdx = dataSource.IndexOf("\\")) != -1) {\r
569                                                 // throw out named instance name\r
570                                                 dataSource = dataSource.Substring(0,instanceIdx);\r
571                                         }\r
572 \r
573                                         if (dataSource != null && dataSource.StartsWith("(") && dataSource.EndsWith(")")) {                                             \r
574                                                 dataSource = dataSource.Substring(1,dataSource.Length - 2);\r
575                                         }\r
576 \r
577                                         if(String.Empty.Equals(dataSource) || (String.Compare("local",dataSource,true) == 0)) {\r
578                                                 dataSource = "localhost";\r
579                                         }\r
580                                 }\r
581                                 return dataSource;\r
582                         }\r
583                 }\r
584 \r
585                 protected virtual string InstanceName\r
586                 {\r
587                         get {\r
588                                 string dataSource = ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_DATA_SOURCE"));\r
589                                 string instanceName = String.Empty;\r
590                                 if (ProviderType == PROVIDER_TYPE.SQLOLEDB) {\r
591                                         int instanceIdx;\r
592                                         if ((instanceIdx = dataSource.IndexOf("\\")) == -1) {\r
593                                                 // no named instance specified - use a default name\r
594                                                 instanceName = StringManager.GetString("SQL_DEFAULT_INSTANCE_NAME");\r
595                                         }\r
596                                         else {\r
597                                                 // get named instance name\r
598                                                 instanceName = dataSource.Substring(instanceIdx + 1);\r
599                                         }\r
600                                 }\r
601                                 return instanceName;\r
602                         }\r
603                 }\r
604 \r
605                 protected virtual string User\r
606                 {\r
607                         get { return ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_USER_ID")); }\r
608                 }\r
609 \r
610                 protected virtual string Password\r
611                 {\r
612                         get { return ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_PASSWORD")); }\r
613                 }\r
614 \r
615                 protected NameValueCollection UserParameters\r
616                 {\r
617                         get {\r
618                                 if (_userParameters == null) {\r
619                                         _userParameters = ConnectionStringHelper.BuildUserParameters(ConnectionString);\r
620                                 }\r
621                                 return _userParameters;\r
622                         }\r
623                 }\r
624 \r
625                 internal String JdbcUrl \r
626                 {\r
627                         get { \r
628                                 if ( UserParameters == null) {\r
629                                         return String.Empty;\r
630                                 }\r
631 \r
632                                 if (_jdbcUrl == null) {\r
633                                         _jdbcUrl = BuildJdbcUrl();\r
634                                 }\r
635                                 return _jdbcUrl;\r
636                         }\r
637                 }\r
638 \r
639                 internal ConnectionState InternalState\r
640                 {\r
641                         get     { return _internalState; }\r
642                 }\r
643 \r
644 \r
645                 protected internal Connection JdbcConnection\r
646                 {\r
647                         get { return _jdbcConnnection; }\r
648                         set { _jdbcConnnection = value; }\r
649                 }\r
650 \r
651                 protected virtual string[] ResourceIgnoredKeys\r
652                 {\r
653                         get { return new string[0]; }\r
654                 }\r
655 \r
656                 protected virtual Hashtable SkippedUserParameters\r
657                 {\r
658                         get { return new Hashtable(new CaseInsensitiveHashCodeProvider(),new CaseInsensitiveComparer()); }\r
659                 }\r
660 \r
661                 internal ObjectNameResolver[] SyntaxPatterns\r
662                 {\r
663                         get {\r
664                                 if (_syntaxPatterns == null) {\r
665                                         _syntaxPatterns = ObjectNamesHelper.GetSyntaxPatterns(this);\r
666                                 }\r
667                                 return _syntaxPatterns;\r
668                         }\r
669                 }\r
670 \r
671                 #endregion // Properties\r
672 \r
673                 #region Methods\r
674                         // since WS also does not permits dynamically change of login timeout and tomcat does no implements - do not do it at all\r
675                         //ds.setLoginTimeout(ConnectionTimeout);\r
676 \r
677                 internal abstract void OnSqlWarning(SQLWarning warning);\r
678 \r
679                 internal abstract void OnStateChanged(ConnectionState orig, ConnectionState current);\r
680 \r
681                 protected abstract SystemException CreateException(SQLException e);\r
682 \r
683                 public override void Close()\r
684                 {\r
685                         try {\r
686                                 ClearReferences();\r
687                                 if (JdbcConnection != null && !JdbcConnection.isClosed()) {\r
688                                         JdbcConnection.close();\r
689                                 }\r
690                         }\r
691                         catch (SQLException e) {\r
692                                 // suppress exception\r
693                                 JdbcConnection = null;\r
694 #if DEBUG\r
695                                 Console.WriteLine("Exception catched at Conection.Close() : {0}\n{1}\n{2}",e.GetType().FullName,e.Message,e.StackTrace);\r
696 #endif\r
697                         }\r
698                         catch (Exception e) {\r
699                                 // suppress exception\r
700                                 JdbcConnection = null;\r
701 #if DEBUG\r
702                                 Console.WriteLine("Exception catched at Conection.Close() : {0}\n{1}\n{2}",e.GetType().FullName,e.Message,e.StackTrace);\r
703 #endif\r
704                         }\r
705                         finally {\r
706                                 lock(_internalStateSync) {\r
707                                         _internalState = ConnectionState.Closed;\r
708                                 }\r
709                         }\r
710                 }\r
711 \r
712                 protected internal virtual void CopyTo(AbstractDBConnection target)\r
713                 {\r
714                         target._connectionString = _connectionString;\r
715                 }\r
716 \r
717                 internal protected virtual void OnSqlException(SQLException exp)\r
718                 {\r
719                         throw CreateException(exp);\r
720                 }\r
721 \r
722                 internal void AddReference(object referencedObject)\r
723                 {       lock(_referencedObjects.SyncRoot) {\r
724                                 _referencedObjects.Add(new WeakReference(referencedObject));\r
725                         }\r
726                 }\r
727 \r
728                 internal void RemoveReference(object referencedObject)\r
729                 {\r
730                         lock(_referencedObjects.SyncRoot) {\r
731                                 for(int i = 0; i < _referencedObjects.Count; i++) {\r
732                                         WeakReference wr = (WeakReference) _referencedObjects[i];\r
733                                         if (wr.IsAlive && (wr.Target == referencedObject)) {\r
734                                                 _referencedObjects.RemoveAt(i);\r
735                                         }\r
736                                 }\r
737                         }\r
738                 }\r
739 \r
740                 private void ClearReferences()\r
741                 {\r
742                         ArrayList oldList = _referencedObjects;\r
743                         _referencedObjects = new ArrayList();\r
744 \r
745                         for(int i = 0; i < oldList.Count; i++) {\r
746                                 WeakReference wr = (WeakReference) oldList[i];\r
747                                 if (wr.IsAlive) {\r
748                                         ClearReference(wr.Target);\r
749                                 }\r
750                         }\r
751                 }\r
752 \r
753                 private void ClearReference(object referencedObject)\r
754                 {\r
755                         try {\r
756                                 if (referencedObject is AbstractDbCommand) {\r
757                                         ((AbstractDbCommand)referencedObject).CloseInternal();\r
758                                 }\r
759                                 else if (referencedObject is AbstractDataReader) {\r
760                                         ((AbstractDataReader)referencedObject).CloseInternal();\r
761                                 }\r
762                         }\r
763                         catch (SQLException) {\r
764                                 // suppress exception since it's possible that command or reader are in inconsistent state\r
765                         }\r
766                 }\r
767 \r
768                 public override void Open()\r
769                 {\r
770                         if (_connectionString == null || _connectionString.Length == 0) {\r
771                                 throw ExceptionHelper.ConnectionStringNotInitialized();\r
772                         }\r
773 \r
774                         IsConnecting = true;\r
775                         try {                   \r
776                                 if (JdbcConnection != null && !JdbcConnection.isClosed()) {\r
777                                         throw ExceptionHelper.ConnectionAlreadyOpen(_internalState);\r
778                                 }\r
779         \r
780                                 switch(JdbcMode) {\r
781                                         case JDBC_MODE.DATA_SOURCE_MODE :\r
782                                                 JdbcConnection = GetConnectionFromDataSource();\r
783                                                 break;\r
784 \r
785                                         case JDBC_MODE.JDBC_DRIVER_MODE:\r
786                                                 JdbcConnection = GetConnectionFromJdbcDriver();\r
787                                                 break;\r
788 \r
789                                         case JDBC_MODE.PROVIDER_MODE :                                  \r
790                                                 JdbcConnection = GetConnectionFromProvider();\r
791                                                 break;\r
792                                 }\r
793                                 IsOpened = true;\r
794 \r
795                                 OnStateChanged(ConnectionState.Closed, ConnectionState.Open);\r
796                         }\r
797                         catch (SQLWarning warning) {\r
798                                 OnSqlWarning(warning);\r
799                         }\r
800                         catch (SQLException exp) {\r
801                                 OnSqlException(exp);\r
802                         }\r
803                         finally {\r
804                                 IsConnecting = false;\r
805                         }\r
806                 }\r
807 \r
808                 public override void ChangeDatabase(String database)\r
809                 {\r
810                         IsConnecting = true;\r
811                         try {\r
812                                 ClearReferences();\r
813                                 Connection con = JdbcConnection;                                \r
814                                 con.setCatalog(database);\r
815                                 ConnectionStringHelper.UpdateValue(UserParameters,StringManager.GetStringArray("CON_DATABASE"),database);\r
816                         }\r
817                         catch (SQLWarning warning) {\r
818                                 OnSqlWarning(warning);\r
819                         }\r
820                         catch (SQLException exp) {\r
821                                 throw CreateException(exp);\r
822                         }\r
823                         finally {\r
824                                 IsConnecting = false;\r
825                         }\r
826                 }\r
827 \r
828                 public override string ServerVersion {\r
829                         get {\r
830                                 // only if the driver support this methods\r
831                                 try {\r
832                                         if (JdbcConnection == null)\r
833                                                 return String.Empty;\r
834 \r
835                                         DatabaseMetaData metaData = JdbcConnection.getMetaData();\r
836                                         return metaData.getDatabaseProductVersion();\r
837                                 }\r
838                                 catch (SQLException exp) {\r
839                                         throw CreateException(exp);\r
840                                 }\r
841                         }\r
842                 }\r
843 \r
844                 internal string JdbcProvider {\r
845                         get {\r
846                                 // only if the driver support this methods\r
847                                 try {\r
848                                         if (JdbcConnection == null)\r
849                                                 return String.Empty;\r
850 \r
851                                         DatabaseMetaData metaData = JdbcConnection.getMetaData();\r
852                                         return metaData.getDriverName() + " " + metaData.getDriverVersion();\r
853                                 }\r
854                                 catch (SQLException exp) {\r
855                                         return String.Empty; //suppress\r
856                                 }\r
857                         }\r
858                 }\r
859 \r
860                 protected override void Dispose(bool disposing)\r
861                 {\r
862                         if (disposing) {\r
863                                 try {\r
864                                         if (JdbcConnection != null && !JdbcConnection.isClosed()) {\r
865                                                 JdbcConnection.close();\r
866                                         }                       \r
867                                         JdbcConnection = null;\r
868                                 }\r
869                                 catch (java.sql.SQLException exp) {\r
870                                         throw CreateException(exp);\r
871                                 }\r
872                         }\r
873                         base.Dispose(disposing);\r
874                 }\r
875 \r
876                 protected internal virtual void ValidateConnectionString(string connectionString)\r
877                 {\r
878                         JDBC_MODE currentJdbcMode = JdbcMode;\r
879                         \r
880                         if (currentJdbcMode == JDBC_MODE.NONE) {\r
881                                 string[] jdbcDriverStr = StringManager.GetStringArray("JDBC_DRIVER");\r
882                                 string[] jdbcUrlStr = StringManager.GetStringArray("JDBC_URL");\r
883                                 bool jdbcDriverSpecified = !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,jdbcDriverStr));\r
884                                 bool jdbcUrlSpecified = !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,jdbcUrlStr));\r
885 \r
886                                 if (jdbcDriverSpecified ^ jdbcUrlSpecified) {\r
887                                         throw new ArgumentException("Invalid format of connection string. If you want to use third-party JDBC driver, the format is: \"JdbcDriverClassName=<jdbc driver class name>;JdbcURL=<jdbc url>\"");\r
888                                 }                               \r
889                         }\r
890                 }\r
891 \r
892                 protected virtual string BuildJdbcUrl()\r
893                 {\r
894                         switch (JdbcMode) {\r
895                                 case JDBC_MODE.JDBC_DRIVER_MODE :\r
896                                         return ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("JDBC_URL"));\r
897                                 default :\r
898                                         return String.Empty;\r
899                         }\r
900                 }\r
901 \r
902                 protected java.util.Properties BuildProperties()\r
903                 {\r
904                         java.util.Properties properties = new java.util.Properties();\r
905 \r
906                         string user = User;\r
907                         if (user != null && user.Length > 0)\r
908                                 properties.put("user", user);\r
909                         string password = Password;\r
910                         if (user != null && user.Length > 0)\r
911                                 properties.put("password", password);\r
912 \r
913                         string[] userKeys = UserParameters.AllKeys;\r
914 \r
915                         for(int i=0; i < userKeys.Length; i++) {\r
916                                 string userKey = userKeys[i];\r
917                                 string userParameter = UserParameters[userKey];\r
918                                 if (!SkipUserParameter(userKey)) {\r
919                                         properties.put(userKey,userParameter);\r
920                                 }\r
921                         }\r
922                         return properties;\r
923                 }\r
924 \r
925                 protected virtual bool SkipUserParameter(string parameterName)\r
926                 {\r
927                         if (SkippedUserParameters.Count == 0) {\r
928                                 // skipped parameters not initialized - skip all\r
929                                 return true;\r
930                         }\r
931 \r
932                         return SkippedUserParameters.Contains(parameterName);\r
933                 }\r
934 \r
935                 protected virtual void InitializeSkippedUserParameters()\r
936                 {\r
937                         if (SkippedUserParameters.Count > 0) {\r
938                                 return;\r
939                         }\r
940 \r
941                         for(int i=0; i < ResourceIgnoredKeys.Length; i++) {\r
942                                 string[] userKeys = StringManager.GetStringArray(ResourceIgnoredKeys[i]);\r
943                                 for(int j=0; j < userKeys.Length; j++) {\r
944                                         SkippedUserParameters.Add(userKeys[j],userKeys[j]);\r
945                                 }\r
946                         }\r
947                 }\r
948  \r
949                 internal void ValidateBeginTransaction()\r
950                 {\r
951                         if (State != ConnectionState.Open) {\r
952                                 throw new InvalidOperationException(Res.GetString("ADP_OpenConnectionRequired_BeginTransaction", new object[] {"BeginTransaction", State}));\r
953                         }\r
954 \r
955                         if (!JdbcConnection.getAutoCommit()) {\r
956                                 throw new System.InvalidOperationException("Parallel transactions are not supported.");\r
957                         }\r
958                 }\r
959 \r
960                 internal virtual Connection GetConnectionFromProvider()\r
961                 {\r
962                         ActivateJdbcDriver(JdbcDriverName);\r
963                         DriverManager.setLoginTimeout(ConnectionTimeout);\r
964                         java.util.Properties properties = BuildProperties();\r
965                         return DriverManager.getConnection (JdbcUrl, properties);\r
966                 }\r
967 \r
968                 internal Connection GetConnectionFromDataSource()\r
969                 {\r
970                         string dataSourceJndi = ConnectionStringHelper.FindValue(UserParameters, StringManager.GetStringArray("CON_JNDI_NAME"));\r
971                         string namingProviderUrl = ConnectionStringHelper.FindValue(UserParameters, StringManager.GetStringArray("CON_JNDI_PROVIDER"));\r
972                         string namingFactoryInitial = ConnectionStringHelper.FindValue(UserParameters, StringManager.GetStringArray("CON_JNDI_FACTORY"));\r
973                         DataSource ds = _dataSourceCache.GetDataSource(dataSourceJndi,namingProviderUrl,namingFactoryInitial);\r
974                         try {\r
975                                 ds.setLoginTimeout(ConnectionTimeout);\r
976                         }\r
977                         catch (java.lang.Exception) {\r
978                                 // WebSphere does not allows dynamicall change of login timeout\r
979                                 // setLoginTimeout is not supported yet\r
980                                 // in Tomcat data source.\r
981                                 // In this case we work wthout timeout.\r
982                         }\r
983                         return ds.getConnection();\r
984                 }\r
985 \r
986                 internal virtual Connection GetConnectionFromJdbcDriver()\r
987                 {\r
988                         string[] jdbcDriverStr = StringManager.GetStringArray("JDBC_DRIVER");\r
989                         string[] jdbcUrlStr = StringManager.GetStringArray("JDBC_URL");\r
990                 \r
991                         string jdbcDriverName = ConnectionStringHelper.FindValue(UserParameters,jdbcDriverStr);\r
992                         string jdbcUrl = ConnectionStringHelper.FindValue(UserParameters,jdbcUrlStr);\r
993 \r
994                         ActivateJdbcDriver(jdbcDriverName);\r
995                         DriverManager.setLoginTimeout(ConnectionTimeout);\r
996 \r
997                         java.util.Properties properties = BuildProperties();\r
998 \r
999                         return DriverManager.getConnection(jdbcUrl,properties);\r
1000                 }\r
1001 \r
1002                 internal ArrayList GetProcedureColumns(String procedureString, AbstractDbCommand command)\r
1003                 {\r
1004                         ArrayList col = new ArrayList();\r
1005                         try {\r
1006                                 ObjectNameResolver[] nameResolvers = SyntaxPatterns;\r
1007                                 ResultSet res = null;\r
1008                                 string catalog = null;\r
1009                                 string schema = null;\r
1010                                 string spname = null;\r
1011                                                 \r
1012                                 DatabaseMetaData metadata = JdbcConnection.getMetaData();       \r
1013                                 bool storesUpperCaseIdentifiers = false;\r
1014                                 bool storesLowerCaseIdentifiers = false;\r
1015                                 try {\r
1016                                         storesUpperCaseIdentifiers = metadata.storesUpperCaseIdentifiers();\r
1017                                         storesLowerCaseIdentifiers = metadata.storesLowerCaseIdentifiers();\r
1018                                 }\r
1019                                 catch (SQLException e) {\r
1020                                         // suppress\r
1021                                 }\r
1022 \r
1023                                 for(int i=0; i < nameResolvers.Length; i++) {\r
1024                                         ObjectNameResolver nameResolver = nameResolvers[i];\r
1025                                         Match match = nameResolver.Match(procedureString);\r
1026 \r
1027                                         if (match.Success) {\r
1028                                                 spname = ObjectNameResolver.GetName(match);                             \r
1029                                                 schema = ObjectNameResolver.GetSchema(match);                                           \r
1030                                                 catalog = ObjectNameResolver.GetCatalog(match);                                         \r
1031 \r
1032                                                 // make all identifiers uppercase or lowercase according to database metadata\r
1033                                                 if (storesUpperCaseIdentifiers) {\r
1034                                                         spname = (spname.Length > 0) ? spname.ToUpper() : null;\r
1035                                                         schema = (schema.Length > 0) ? schema.ToUpper() : null;\r
1036                                                         catalog = (catalog.Length > 0) ? catalog.ToUpper() : null;\r
1037                                                 }\r
1038                                                 else if (storesLowerCaseIdentifiers) {\r
1039                                                         spname = (spname.Length > 0) ? spname.ToLower() : null;\r
1040                                                         schema = (schema.Length > 0) ? schema.ToLower() : null;\r
1041                                                         catalog = (catalog.Length > 0) ? catalog.ToLower() : null;\r
1042                                                 }\r
1043                                                 else {\r
1044                                                         spname = (spname.Length > 0) ? spname : null;\r
1045                                                         schema = (schema.Length > 0) ? schema : null;\r
1046                                                         catalog = (catalog.Length > 0) ? catalog : null;\r
1047                                                 }\r
1048 \r
1049                                                 // catalog from db is always in correct caps\r
1050                                                 if (catalog == null) {\r
1051                                                         catalog = JdbcConnection.getCatalog();\r
1052                                                 }\r
1053 \r
1054                                                 try {\r
1055                                                         // always get the first procedure that db returns\r
1056                                                         res = metadata.getProcedures(catalog, schema, spname);                                                                                          \r
1057                                                         if (res.next()) {\r
1058                                                                 catalog = res.getString(1);\r
1059                                                                 schema = res.getString(2);\r
1060                                                                 spname = res.getString(3);\r
1061                                                                 break;\r
1062                                                         }\r
1063 \r
1064                                                         spname = null;\r
1065                                                 }\r
1066                                                 catch { // suppress exception\r
1067                                                         return null;\r
1068                                                 }\r
1069                                                 finally {\r
1070                                                         if (res != null) {\r
1071                                                                 res.close();\r
1072                                                         }\r
1073                                                 }\r
1074                                         }\r
1075                                 }       \r
1076                 \r
1077                                 if (spname == null || spname.Length == 0) {\r
1078                                         return null;\r
1079                                 }\r
1080                                 \r
1081                                 try {\r
1082                                         // get procedure columns based o  procedure metadata\r
1083                                         res = metadata.getProcedureColumns(catalog, schema, spname, null);                              \r
1084                                         while (res.next()) {\r
1085                                                 // since there is still a possibility that some of the parameters to getProcedureColumn were nulls, \r
1086                                                 // we need to filter the results with strict matching\r
1087                                                 if ((res.getString(1) != catalog ) || (res.getString(2) != schema) || (res.getString(3) != spname)) {\r
1088                                                         continue;\r
1089                                                 }\r
1090 \r
1091                                                 AbstractDbParameter parameter = (AbstractDbParameter)command.CreateParameter();\r
1092                                                 \r
1093                                                 parameter.SetParameterName(res);\r
1094                                                 parameter.SetParameterDbType(res);\r
1095                                                 parameter.SetSpecialFeatures(res);\r
1096 \r
1097                                                 //get parameter direction\r
1098                                                 short direction = res.getShort("COLUMN_TYPE");\r
1099                                                 if(direction == 1) //DatabaseMetaData.procedureColumnIn\r
1100                                                         parameter.Direction = ParameterDirection.Input;\r
1101                                                 else if(direction == 2) //DatabaseMetaData.procedureColumnInOut\r
1102                                                         parameter.Direction = ParameterDirection.InputOutput;\r
1103                                                 else if(direction == 4) //DatabaseMetaData.procedureColumnOut\r
1104                                                         parameter.Direction = ParameterDirection.Output;\r
1105                                                 else if(direction == 5) //DatabaseMetaData.procedureColumnReturn\r
1106                                                         parameter.Direction = ParameterDirection.ReturnValue;\r
1107                                         \r
1108                                                 //get parameter precision and scale\r
1109                                                 parameter.SetParameterPrecisionAndScale(res);\r
1110 \r
1111                                                 parameter.SetParameterSize(res);\r
1112                                                 parameter.SetParameterIsNullable(res);\r
1113 \r
1114                                                 col.Add(parameter);\r
1115                                         }\r
1116                                 }\r
1117                                 finally {\r
1118                                         if (res != null) {\r
1119                                                 res.close();\r
1120                                         }\r
1121                                 }                               \r
1122                         }\r
1123                         catch(Exception e) {\r
1124                                 //supress\r
1125 #if DEBUG\r
1126                                 Console.WriteLine("Exception catched at AbstractDBConnection.GetProcedureColumns() : {0}\n{1}\n{2}",e.GetType().FullName,e.Message,e.StackTrace);\r
1127 #endif\r
1128                         }\r
1129                         return col;\r
1130                 }\r
1131 \r
1132                 protected static void ActivateJdbcDriver(string driver)\r
1133                 {\r
1134                         if(driver != null) {\r
1135                                 try {\r
1136                                         java.lang.Class.forName(driver).newInstance();\r
1137                                 }\r
1138                                 catch (java.lang.ClassNotFoundException e) {\r
1139                                         throw new TypeLoadException(e.Message);\r
1140                                 }\r
1141                                 catch (java.lang.InstantiationException e) {\r
1142                                         throw new MemberAccessException(e.Message);\r
1143                                 }\r
1144                 catch (java.lang.IllegalAccessException e) {\r
1145                                         throw new MissingMethodException(e.Message);\r
1146                                 }\r
1147                         }\r
1148                 }\r
1149 \r
1150                 protected String BuildMsSqlUrl()\r
1151                 {\r
1152                         return StringManager.GetString("SQL_JDBC_URL") //"jdbc:microsoft:sqlserver://"\r
1153                                 + ServerName + ":" + Port + ";DatabaseName=" + CatalogName;\r
1154                 }\r
1155 \r
1156                 #endregion // Methods   \r
1157         }\r
1158 }