2 // System.Data.OleDb.OleDbConnection
5 // Konstantin Triger <kostat@mainsoft.com>
6 // Boris Kirzner <borisk@mainsoft.com>
8 // (C) 2006 Mainsoft Corporation (http://www.mainsoft.com)
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:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
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.
33 using System
.Collections
;
34 using System
.Data
.Common
;
35 using System
.Data
.Configuration
;
36 using System
.Data
.ProviderBase
;
37 using Mainsoft
.Data
.Configuration
;
40 using System
.Globalization
;
42 namespace Mainsoft
.Data
.Jdbc
.Providers
44 #region OleDbSqlServerProvider2000
46 public class OleDbSqlServerProvider2000
: GenericProvider
50 private const string Port
= "Port";
51 private const string DefaultInstanceName
= "MSSQLSERVER";
52 private const int DefaultTimeout
= 15;
62 public OleDbSqlServerProvider2000 (IDictionary providerInfo
) : base (providerInfo
)
66 #endregion // Constructors
70 #endregion // Properties
74 public override IConnectionStringDictionary
GetConnectionStringBuilder (string connectionString
)
76 //TBD: should wrap the IConnectionStringDictionary
77 IConnectionStringDictionary conectionStringBuilder
= base.GetConnectionStringBuilder (connectionString
);
78 OleDbSqlHelper
.InitConnectionStringBuilder (conectionStringBuilder
);
80 string port
= (string) conectionStringBuilder
[Port
];
81 if (port
== null || port
.Length
== 0) {
82 port
= GetMSSqlPort (OleDbSqlHelper
.GetInstanceName (conectionStringBuilder
, DefaultInstanceName
), OleDbSqlHelper
.GetDataSource (conectionStringBuilder
), OleDbSqlHelper
.GetTimeout (conectionStringBuilder
, DefaultTimeout
));
83 conectionStringBuilder
.Add (Port
, port
);
86 return conectionStringBuilder
;
89 static string GetMSSqlPort(string instanceName
, string dataSource
, int timeout
) {
90 string port
= String
.Empty
;
92 DatagramSocket socket
= new DatagramSocket();
95 sbyte[] buf
= new sbyte[] {2}
;
96 InetAddress address
= InetAddress
.getByName(dataSource
);
97 DatagramPacket packet
= new DatagramPacket(buf
, buf
.Length
, address
, 1434);
99 sbyte[] recbuf
= new sbyte[1024];
100 packet
= new DatagramPacket(recbuf
, recbuf
.Length
, packet
.getAddress(), packet
.getPort());
102 // try to receive from socket while increasing timeouts in geometric progression
103 int iterationTimeout
= 1;
104 int totalTimeout
= 0;
106 socket
.setSoTimeout(iterationTimeout
);
108 socket
.receive(packet
);
111 catch (SocketTimeoutException e
) {
112 totalTimeout
+= iterationTimeout
;
113 iterationTimeout
*= 2;
114 if (totalTimeout
>= timeout
*1000) {
115 throw new java
.sql
.SQLException(
116 String
.Format ("Unable to retrieve the port number for {0} using UDP on port 1434. Please see your network administrator to solve this problem or add the port number of your SQL server instance to your connection string (i.e. port=1433).", dataSource
)
121 sbyte[] rcvdSbytes
= packet
.getData();
122 char[] rcvdChars
= new char[rcvdSbytes
.Length
];
123 for(int i
=0; i
< rcvdSbytes
.Length
; i
++) {
124 rcvdChars
[i
] = (char)rcvdSbytes
[i
];
126 String received
= new String(rcvdChars
);
128 java
.util
.StringTokenizer st
= new java
.util
.StringTokenizer(received
, ";");
130 bool instanceReached
= instanceName
== null || instanceName
.Length
== 0;
131 while (st
.hasMoreTokens()) {
132 if (!instanceReached
) {
133 if (prev
.Trim().Equals("InstanceName")) {
134 if (String
.Compare(instanceName
,st
.nextToken().Trim(),true, CultureInfo
.InvariantCulture
) == 0) {
135 instanceReached
= true;
140 if (prev
.Trim().Equals("tcp")) {
141 port
= st
.nextToken().Trim();
142 //ensure we got a valid int
143 java
.lang
.Integer
.parseInt(port
);
147 prev
= st
.nextToken();
151 if (!instanceReached
)
152 throw new java
.sql
.SQLException(
153 String
.Format ("Specified SQL Server '{0}\\{1}' not found.", dataSource
, instanceName
)
158 catch (java
.sql
.SQLException
) {
161 catch (Exception e
) {
162 throw new java
.sql
.SQLException(e
.Message
);
166 #endregion // Methods
169 #endregion // OleDbSqlServerProvider2000
171 #region OleDbSqlServerProvider2005
173 public class OleDbSqlServerProvider2005
: GenericProvider
185 public OleDbSqlServerProvider2005 (IDictionary providerInfo
) : base (providerInfo
)
189 #endregion // Constructors
193 #endregion // Properties
197 public override IConnectionStringDictionary
GetConnectionStringBuilder (string connectionString
)
199 //TBD: should wrap the IConnectionStringDictionary
200 IConnectionStringDictionary conectionStringBuilder
= base.GetConnectionStringBuilder (connectionString
);
201 OleDbSqlHelper
.InitConnectionStringBuilder (conectionStringBuilder
);
202 return conectionStringBuilder
;
205 public override java
.sql
.Connection
GetConnection(IConnectionStringDictionary conectionStringBuilder
)
207 return new SqlServer2005Connection (base.GetConnection (conectionStringBuilder
));
210 #endregion // Methods
212 #region SqlServer2005Connection
214 sealed class SqlServer2005Connection
: Connection
218 public SqlServer2005Connection(java
.sql
.Connection connection
) : base (connection
)
226 public override java
.sql
.DatabaseMetaData
getMetaData()
228 return new SqlServer2005DatabaseMetaData (base.getMetaData ());
236 #region SqlServer2005DatabaseMetaData
238 sealed class SqlServer2005DatabaseMetaData
: DatabaseMetaData
246 public SqlServer2005DatabaseMetaData (java
.sql
.DatabaseMetaData databaseMetaData
) : base (databaseMetaData
)
250 #endregion // Constructors
254 #endregion // Properties
258 public override java
.sql
.ResultSet
getProcedureColumns(string arg_0
, string arg_1
, string arg_2
, string arg_3
)
260 return new SqlServer2005DatbaseMetaDataResultSet (Wrapped
.getProcedureColumns (arg_0
, arg_1
, arg_2
, arg_3
));
263 #endregion // Methods
268 #region SqlServer2005DatbaseMetaDataResultSet
270 sealed class SqlServer2005DatbaseMetaDataResultSet
: ResultSet
274 private const string DataType
= "DATA_TYPE";
284 public SqlServer2005DatbaseMetaDataResultSet (java
.sql
.ResultSet resultSet
) : base (resultSet
)
288 #endregion // Constructors
292 #endregion // Properties
296 public override int getInt(int arg_0
)
298 int res
= base.getInt (arg_0
);
299 if (res
== -9) // sql server 2005 jdbc driver value for NVARCHAR
300 if (String
.CompareOrdinal (getMetaData ().getColumnName (arg_0
), DataType
) == 0)
301 return java
.sql
.Types
.VARCHAR
;
302 if (res
== -8) // sql server 2005 jdbc driver value for NVARCHAR
303 if (String
.CompareOrdinal (getMetaData ().getColumnName (arg_0
), DataType
) == 0)
304 return java
.sql
.Types
.CHAR
;
308 public override int getInt(string arg_0
)
310 int res
= base.getInt (arg_0
);
312 if (res
== -9) // sql server 2005 jdbc driver value for NVARCHAR
313 if (String
.CompareOrdinal (arg_0
, DataType
) == 0)
314 return java
.sql
.Types
.VARCHAR
;
316 if (res
== -8) // sql server 2005 jdbc driver value for NVARCHAR
317 if (String
.CompareOrdinal (arg_0
, DataType
) == 0)
318 return java
.sql
.Types
.CHAR
;
322 #endregion // Methods
328 #endregion // OleDbSqlServerProvider2005
330 #region OleDbSqlHelper
334 private const string Database
= "Database";
335 private const string ServerName
= "ServerName";
336 private const string Timeout
= "Timeout";
338 internal static void InitConnectionStringBuilder (IConnectionStringDictionary conectionStringBuilder
)
340 if (!conectionStringBuilder
.Contains("jndi-datasource-name")) {
342 string database
= (string) conectionStringBuilder
[Database
];
343 if (database
== null)
344 conectionStringBuilder
.Add (Database
, String
.Empty
);
346 string dataSource
= GetDataSource (conectionStringBuilder
);
347 string instanceName
= GetInstanceName (conectionStringBuilder
, null);
349 if (instanceName
!= null)
350 conectionStringBuilder
[ServerName
] = dataSource
+ "\\" + instanceName
;
352 conectionStringBuilder
[ServerName
] = dataSource
;
356 // TBD : refactor GetInstanceName and GetDataSource to single method
357 internal static string GetInstanceName (IDictionary keyMapper
, string defaultInstanceName
)
359 string dataSource
= (string) keyMapper
[ServerName
];
360 string instanceName
= String
.Empty
;
362 if (dataSource
== null || (instanceIdx
= dataSource
.IndexOf ("\\")) == -1)
363 // no named instance specified - use a default name
364 return defaultInstanceName
;
366 // get named instance name
367 return dataSource
.Substring (instanceIdx
+ 1);
370 internal static string GetDataSource (IDictionary keyMapper
)
372 string dataSource
= (string) keyMapper
[ServerName
];
374 if (dataSource
!= null && (instanceIdx
= dataSource
.IndexOf ("\\")) != -1)
375 // throw out named instance name
376 dataSource
= dataSource
.Substring (0,instanceIdx
);
378 if (dataSource
!= null && dataSource
.StartsWith ("(") && dataSource
.EndsWith (")"))
379 dataSource
= dataSource
.Substring (1,dataSource
.Length
- 2);
381 if (String
.Empty
.Equals (dataSource
) || (String
.Compare ("local", dataSource
, true, CultureInfo
.InvariantCulture
) == 0) || (String
.CompareOrdinal (".", dataSource
) == 0))
382 dataSource
= "localhost";
387 internal static int GetTimeout (IDictionary keyMapper
, int defaultTimeout
)
389 string timeoutStr
= (string) keyMapper
[Timeout
];
390 if ((timeoutStr
!= null) && (timeoutStr
.Length
!= 0)) {
392 return Convert
.ToInt32(timeoutStr
);
394 catch(FormatException e
) {
395 throw ExceptionHelper
.InvalidValueForKey("connect timeout");
397 catch (OverflowException e
) {
398 throw ExceptionHelper
.InvalidValueForKey("connect timeout");
401 return defaultTimeout
;
405 #endregion // OleDbSqlHelper