1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.datasource.unpooled;
17
18 import java.io.PrintWriter;
19 import java.sql.Connection;
20 import java.sql.Driver;
21 import java.sql.DriverManager;
22 import java.sql.DriverPropertyInfo;
23 import java.sql.SQLException;
24 import java.util.Enumeration;
25 import java.util.Map;
26 import java.util.Properties;
27 import java.util.concurrent.ConcurrentHashMap;
28 import java.util.concurrent.Executors;
29 import java.util.logging.Logger;
30
31 import javax.sql.DataSource;
32
33 import org.apache.ibatis.io.Resources;
34
35
36
37
38
39 public class UnpooledDataSource implements DataSource {
40
41 private ClassLoader driverClassLoader;
42 private Properties driverProperties;
43 private static Map<String, Driver> registeredDrivers = new ConcurrentHashMap<>();
44
45 private String driver;
46 private String url;
47 private String username;
48 private String password;
49
50 private Boolean autoCommit;
51 private Integer defaultTransactionIsolationLevel;
52 private Integer defaultNetworkTimeout;
53
54 static {
55 Enumeration<Driver> drivers = DriverManager.getDrivers();
56 while (drivers.hasMoreElements()) {
57 Driver driver = drivers.nextElement();
58 registeredDrivers.put(driver.getClass().getName(), driver);
59 }
60 }
61
62 public UnpooledDataSource() {
63 }
64
65 public UnpooledDataSource(String driver, String url, String username, String password) {
66 this.driver = driver;
67 this.url = url;
68 this.username = username;
69 this.password = password;
70 }
71
72 public UnpooledDataSource(String driver, String url, Properties driverProperties) {
73 this.driver = driver;
74 this.url = url;
75 this.driverProperties = driverProperties;
76 }
77
78 public UnpooledDataSource(ClassLoader driverClassLoader, String driver, String url, String username, String password) {
79 this.driverClassLoader = driverClassLoader;
80 this.driver = driver;
81 this.url = url;
82 this.username = username;
83 this.password = password;
84 }
85
86 public UnpooledDataSource(ClassLoader driverClassLoader, String driver, String url, Properties driverProperties) {
87 this.driverClassLoader = driverClassLoader;
88 this.driver = driver;
89 this.url = url;
90 this.driverProperties = driverProperties;
91 }
92
93 @Override
94 public Connection getConnection() throws SQLException {
95 return doGetConnection(username, password);
96 }
97
98 @Override
99 public Connection getConnection(String username, String password) throws SQLException {
100 return doGetConnection(username, password);
101 }
102
103 @Override
104 public void setLoginTimeout(int loginTimeout) {
105 DriverManager.setLoginTimeout(loginTimeout);
106 }
107
108 @Override
109 public int getLoginTimeout() {
110 return DriverManager.getLoginTimeout();
111 }
112
113 @Override
114 public void setLogWriter(PrintWriter logWriter) {
115 DriverManager.setLogWriter(logWriter);
116 }
117
118 @Override
119 public PrintWriter getLogWriter() {
120 return DriverManager.getLogWriter();
121 }
122
123 public ClassLoader getDriverClassLoader() {
124 return driverClassLoader;
125 }
126
127 public void setDriverClassLoader(ClassLoader driverClassLoader) {
128 this.driverClassLoader = driverClassLoader;
129 }
130
131 public Properties getDriverProperties() {
132 return driverProperties;
133 }
134
135 public void setDriverProperties(Properties driverProperties) {
136 this.driverProperties = driverProperties;
137 }
138
139 public synchronized String getDriver() {
140 return driver;
141 }
142
143 public synchronized void setDriver(String driver) {
144 this.driver = driver;
145 }
146
147 public String getUrl() {
148 return url;
149 }
150
151 public void setUrl(String url) {
152 this.url = url;
153 }
154
155 public String getUsername() {
156 return username;
157 }
158
159 public void setUsername(String username) {
160 this.username = username;
161 }
162
163 public String getPassword() {
164 return password;
165 }
166
167 public void setPassword(String password) {
168 this.password = password;
169 }
170
171 public Boolean isAutoCommit() {
172 return autoCommit;
173 }
174
175 public void setAutoCommit(Boolean autoCommit) {
176 this.autoCommit = autoCommit;
177 }
178
179 public Integer getDefaultTransactionIsolationLevel() {
180 return defaultTransactionIsolationLevel;
181 }
182
183 public void setDefaultTransactionIsolationLevel(Integer defaultTransactionIsolationLevel) {
184 this.defaultTransactionIsolationLevel = defaultTransactionIsolationLevel;
185 }
186
187
188
189
190
191
192
193 public Integer getDefaultNetworkTimeout() {
194 return defaultNetworkTimeout;
195 }
196
197
198
199
200
201
202
203
204 public void setDefaultNetworkTimeout(Integer defaultNetworkTimeout) {
205 this.defaultNetworkTimeout = defaultNetworkTimeout;
206 }
207
208 private Connection doGetConnection(String username, String password) throws SQLException {
209 Properties props = new Properties();
210 if (driverProperties != null) {
211 props.putAll(driverProperties);
212 }
213 if (username != null) {
214 props.setProperty("user", username);
215 }
216 if (password != null) {
217 props.setProperty("password", password);
218 }
219 return doGetConnection(props);
220 }
221
222 private Connection doGetConnection(Properties properties) throws SQLException {
223 initializeDriver();
224 Connection connection = DriverManager.getConnection(url, properties);
225 configureConnection(connection);
226 return connection;
227 }
228
229 private synchronized void initializeDriver() throws SQLException {
230 if (!registeredDrivers.containsKey(driver)) {
231 Class<?> driverType;
232 try {
233 if (driverClassLoader != null) {
234 driverType = Class.forName(driver, true, driverClassLoader);
235 } else {
236 driverType = Resources.classForName(driver);
237 }
238
239
240 Driver driverInstance = (Driver) driverType.getDeclaredConstructor().newInstance();
241 DriverManager.registerDriver(new DriverProxy(driverInstance));
242 registeredDrivers.put(driver, driverInstance);
243 } catch (Exception e) {
244 throw new SQLException("Error setting driver on UnpooledDataSource. Cause: " + e);
245 }
246 }
247 }
248
249 private void configureConnection(Connection conn) throws SQLException {
250 if (defaultNetworkTimeout != null) {
251 conn.setNetworkTimeout(Executors.newSingleThreadExecutor(), defaultNetworkTimeout);
252 }
253 if (autoCommit != null && autoCommit != conn.getAutoCommit()) {
254 conn.setAutoCommit(autoCommit);
255 }
256 if (defaultTransactionIsolationLevel != null) {
257 conn.setTransactionIsolation(defaultTransactionIsolationLevel);
258 }
259 }
260
261 private static class DriverProxy implements Driver {
262 private Driver driver;
263
264 DriverProxy(Driver d) {
265 this.driver = d;
266 }
267
268 @Override
269 public boolean acceptsURL(String u) throws SQLException {
270 return this.driver.acceptsURL(u);
271 }
272
273 @Override
274 public Connection connect(String u, Properties p) throws SQLException {
275 return this.driver.connect(u, p);
276 }
277
278 @Override
279 public int getMajorVersion() {
280 return this.driver.getMajorVersion();
281 }
282
283 @Override
284 public int getMinorVersion() {
285 return this.driver.getMinorVersion();
286 }
287
288 @Override
289 public DriverPropertyInfo[] getPropertyInfo(String u, Properties p) throws SQLException {
290 return this.driver.getPropertyInfo(u, p);
291 }
292
293 @Override
294 public boolean jdbcCompliant() {
295 return this.driver.jdbcCompliant();
296 }
297
298 @Override
299 public Logger getParentLogger() {
300 return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
301 }
302 }
303
304 @Override
305 public <T> T unwrap(Class<T> iface) throws SQLException {
306 throw new SQLException(getClass().getName() + " is not a wrapper.");
307 }
308
309 @Override
310 public boolean isWrapperFor(Class<?> iface) throws SQLException {
311 return false;
312 }
313
314 @Override
315 public Logger getParentLogger() {
316
317 return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
318 }
319
320 }