imported everything from my branch (which is slightly harmless).
[mono.git] / mcs / class / System.Data / System.Data.OleDb.jvm / OleDbConnectionFactory.cs
1 //\r
2 // System.Data.OleDb.OleDbConnectionFactory\r
3 //
4 // Authors:
5 //      Konstantin Triger <kostat@mainsoft.com>
6 //      Boris Kirzner <borisk@mainsoft.com>
7 //      
8 // (C) 2005 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 //\r
31 \r
32 \r
33 \r
34 using System;\r
35 using System.Data;\r
36 using System.Data.Common;\r
37 using System.Reflection;\r
38 using System.Collections;\r
39 \r
40 namespace System.Data.OleDb\r
41 {\r
42         internal class OleDbConnectionFactory\r
43         {\r
44                 private static Object LockObj = new Object();\r
45                 private static Hashtable dataSourceCache = new Hashtable();\r
46                 private static Type OracleConnectionCacheImplType = Type.GetType("oracle.jdbc.pool.OracleConnectionCacheImpl");\r
47                                                                                                                                                   \r
48                 private static MethodInfo setUrlMethod = OracleConnectionCacheImplType.GetMethod("setURL", BindingFlags.Public | BindingFlags.Instance);\r
49                 private static MethodInfo setUserMethod = OracleConnectionCacheImplType.GetMethod("setUser", BindingFlags.Public | BindingFlags.Instance);\r
50                 private static MethodInfo setPasswordMethod = OracleConnectionCacheImplType.GetMethod("setPassword", BindingFlags.Public | BindingFlags.Instance);\r
51                 private static MethodInfo getActiveSizeMethod = OracleConnectionCacheImplType.GetMethod("getActiveSize", BindingFlags.Public | BindingFlags.Instance);\r
52                 private static MethodInfo closeMethod = OracleConnectionCacheImplType.GetMethod("close", BindingFlags.Public | BindingFlags.Instance);\r
53                 private static MethodInfo setMaxLimitMethod = OracleConnectionCacheImplType.GetMethod("setMaxLimit", BindingFlags.Public | BindingFlags.Instance);\r
54                 private static MethodInfo setMinLimitMethod = OracleConnectionCacheImplType.GetMethod("setMinLimit", BindingFlags.Public | BindingFlags.Instance);\r
55                 private static long timestamp = DateTime.Now.Ticks;\r
56                 private static int MINUTES_TIMEOUT = 60;\r
57 \r
58                 private static DbStringManager StringManager = new DbStringManager("System.Data.System.Data.ProviderBase.jvm.OleDbStrings");\r
59 \r
60                 internal static java.sql.Connection GetConnection(OleDbConnection.PROVIDER_TYPE providerType,String url,String user,String password,int timeout)\r
61                 {\r
62                         CacheKey key = new CacheKey(url,user,password);\r
63                         Object dataSourceObj;\r
64                         lock(LockObj) \r
65                         {\r
66                                 if (TimeIsOver())\r
67                                         Clear();\r
68 \r
69                                 dataSourceObj = dataSourceCache[key];\r
70                                 if (dataSourceObj == null) \r
71                                 {\r
72                                         switch(providerType) \r
73                                         {\r
74                                                 case OleDbConnection.PROVIDER_TYPE.MSDAORA :                                    \r
75                                         \r
76                                                         dataSourceObj = Activator.CreateInstance(OracleConnectionCacheImplType);\r
77                                         \r
78                                                         Object[] setUrlArgs = new Object[1] { url };\r
79                                                         Object[] setUserArgs = new Object[1] { user };\r
80                                                         Object[] setPasswordArgs = new Object[1] { password };\r
81 \r
82                                                         setUrlMethod.Invoke(dataSourceObj,setUrlArgs);\r
83                                                         setUserMethod.Invoke(dataSourceObj,setUserArgs);\r
84                                                         setPasswordMethod.Invoke(dataSourceObj,setPasswordArgs);\r
85 \r
86                                                         int maxLimit = Convert.ToInt32(StringManager.GetString("ORA_CONNECTION_POOLING_MAX_LIMIT","-1"));\r
87                                                         int minLimit = Convert.ToInt32(StringManager.GetString("ORA_CONNECTION_POOLING_MIN_LIMIT","-1"));\r
88 \r
89                                                         if(minLimit != -1)\r
90                                                                 setMinLimitMethod.Invoke(dataSourceObj,new Object[1] { minLimit } );\r
91 \r
92                                                         if(maxLimit != -1)\r
93                                                                 setMaxLimitMethod.Invoke(dataSourceObj,new Object[1] { maxLimit } );\r
94 \r
95                                                         break;\r
96                                         }\r
97                                         dataSourceCache.Add(key,dataSourceObj);\r
98                                 }\r
99                         }\r
100 \r
101                         java.sql.Connection conn;\r
102                         lock(dataSourceObj) {\r
103                                 if (((javax.sql.DataSource)dataSourceObj).getLoginTimeout() != timeout) {\r
104                                         ((javax.sql.DataSource)dataSourceObj).setLoginTimeout(timeout);\r
105                                 }\r
106                                 conn = ((javax.sql.DataSource)dataSourceObj).getConnection();\r
107                         }\r
108                         return conn;\r
109                 }\r
110 \r
111                 private static bool TimeIsOver() \r
112                 {\r
113                                 return (DateTime.Now.Ticks - timestamp > MINUTES_TIMEOUT * TimeSpan.TicksPerMinute);\r
114                 }\r
115 \r
116                 private static void Clear() \r
117                 {\r
118                         ArrayList closedDataSources = new ArrayList();\r
119 \r
120                         // collect all the datasources with no connections in use\r
121                         foreach(DictionaryEntry e in dataSourceCache)\r
122                         {\r
123                                 Object dataSourceObj = e.Value;\r
124                                 Object dataSourceObjKey = e.Key;\r
125 \r
126                                 if (getActiveSizeMethod.Invoke(dataSourceObj,new object[0]).Equals(0)) {\r
127                                         closeMethod.Invoke(dataSourceObj,new object[0]);\r
128                                         closedDataSources.Add(dataSourceObjKey);\r
129                                 }\r
130                         }\r
131 \r
132                         // close and remove all data sources with no connections in use\r
133                         foreach(Object dataSourceObjKey in closedDataSources) {\r
134                                 dataSourceCache.Remove(dataSourceObjKey);\r
135                         }       \r
136                 }\r
137         }\r
138 \r
139         // Key for data sources cache\r
140         // data sources mapped by jdbc url, user and password\r
141         internal class CacheKey\r
142     {\r
143         private String url;\r
144         private String user;\r
145         private String password;\r
146 \r
147         public CacheKey(String url, String user, String password)\r
148         {\r
149             this.url = url;\r
150             this.user = user;\r
151             this.password = password;\r
152         }\r
153 \r
154         public bool equals(Object o)\r
155         {\r
156             if (this == o) return true;\r
157             if (!(o is CacheKey)) return false;\r
158 \r
159             CacheKey cacheKey = (CacheKey) o;\r
160 \r
161             if (!password.Equals(cacheKey.password)) return false;\r
162             if (!url.Equals(cacheKey.url)) return false;\r
163             if (!user.Equals(cacheKey.user)) return false;\r
164 \r
165             return true;\r
166         }\r
167 \r
168         public int hashCode()\r
169         {\r
170             int result;\r
171             result = url.GetHashCode();\r
172             result = 29 * result + user.GetHashCode();\r
173             result = 29 * result + password.GetHashCode();\r
174             return result;\r
175         }\r
176     }\r
177 }\r