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 final 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,
79 String password) {
80 this.driverClassLoader = driverClassLoader;
81 this.driver = driver;
82 this.url = url;
83 this.username = username;
84 this.password = password;
85 }
86
87 public UnpooledDataSource(ClassLoader driverClassLoader, String driver, String url, Properties driverProperties) {
88 this.driverClassLoader = driverClassLoader;
89 this.driver = driver;
90 this.url = url;
91 this.driverProperties = driverProperties;
92 }
93
94 @Override
95 public Connection getConnection() throws SQLException {
96 return doGetConnection(username, password);
97 }
98
99 @Override
100 public Connection getConnection(String username, String password) throws SQLException {
101 return doGetConnection(username, password);
102 }
103
104 @Override
105 public void setLoginTimeout(int loginTimeout) {
106 DriverManager.setLoginTimeout(loginTimeout);
107 }
108
109 @Override
110 public int getLoginTimeout() {
111 return DriverManager.getLoginTimeout();
112 }
113
114 @Override
115 public void setLogWriter(PrintWriter logWriter) {
116 DriverManager.setLogWriter(logWriter);
117 }
118
119 @Override
120 public PrintWriter getLogWriter() {
121 return DriverManager.getLogWriter();
122 }
123
124 public ClassLoader getDriverClassLoader() {
125 return driverClassLoader;
126 }
127
128 public void setDriverClassLoader(ClassLoader driverClassLoader) {
129 this.driverClassLoader = driverClassLoader;
130 }
131
132 public Properties getDriverProperties() {
133 return driverProperties;
134 }
135
136 public void setDriverProperties(Properties driverProperties) {
137 this.driverProperties = driverProperties;
138 }
139
140 public synchronized String getDriver() {
141 return driver;
142 }
143
144 public synchronized void setDriver(String driver) {
145 this.driver = driver;
146 }
147
148 public String getUrl() {
149 return url;
150 }
151
152 public void setUrl(String url) {
153 this.url = url;
154 }
155
156 public String getUsername() {
157 return username;
158 }
159
160 public void setUsername(String username) {
161 this.username = username;
162 }
163
164 public String getPassword() {
165 return password;
166 }
167
168 public void setPassword(String password) {
169 this.password = password;
170 }
171
172 public Boolean isAutoCommit() {
173 return autoCommit;
174 }
175
176 public void setAutoCommit(Boolean autoCommit) {
177 this.autoCommit = autoCommit;
178 }
179
180 public Integer getDefaultTransactionIsolationLevel() {
181 return defaultTransactionIsolationLevel;
182 }
183
184 public void setDefaultTransactionIsolationLevel(Integer defaultTransactionIsolationLevel) {
185 this.defaultTransactionIsolationLevel = defaultTransactionIsolationLevel;
186 }
187
188
189
190
191
192
193
194
195 public Integer getDefaultNetworkTimeout() {
196 return defaultNetworkTimeout;
197 }
198
199
200
201
202
203
204
205
206
207
208 public void setDefaultNetworkTimeout(Integer defaultNetworkTimeout) {
209 this.defaultNetworkTimeout = defaultNetworkTimeout;
210 }
211
212 private Connection doGetConnection(String username, String password) throws SQLException {
213 Properties props = new Properties();
214 if (driverProperties != null) {
215 props.putAll(driverProperties);
216 }
217 if (username != null) {
218 props.setProperty("user", username);
219 }
220 if (password != null) {
221 props.setProperty("password", password);
222 }
223 return doGetConnection(props);
224 }
225
226 private Connection doGetConnection(Properties properties) throws SQLException {
227 initializeDriver();
228 Connection connection = DriverManager.getConnection(url, properties);
229 configureConnection(connection);
230 return connection;
231 }
232
233 private synchronized void initializeDriver() throws SQLException {
234 if (!registeredDrivers.containsKey(driver)) {
235 Class<?> driverType;
236 try {
237 if (driverClassLoader != null) {
238 driverType = Class.forName(driver, true, driverClassLoader);
239 } else {
240 driverType = Resources.classForName(driver);
241 }
242
243
244 Driver driverInstance = (Driver) driverType.getDeclaredConstructor().newInstance();
245 DriverManager.registerDriver(new DriverProxy(driverInstance));
246 registeredDrivers.put(driver, driverInstance);
247 } catch (Exception e) {
248 throw new SQLException("Error setting driver on UnpooledDataSource. Cause: " + e);
249 }
250 }
251 }
252
253 private void configureConnection(Connection conn) throws SQLException {
254 if (defaultNetworkTimeout != null) {
255 conn.setNetworkTimeout(Executors.newSingleThreadExecutor(), defaultNetworkTimeout);
256 }
257 if (autoCommit != null && autoCommit != conn.getAutoCommit()) {
258 conn.setAutoCommit(autoCommit);
259 }
260 if (defaultTransactionIsolationLevel != null) {
261 conn.setTransactionIsolation(defaultTransactionIsolationLevel);
262 }
263 }
264
265 private static class DriverProxy implements Driver {
266 private final Driver driver;
267
268 DriverProxy(Driver d) {
269 this.driver = d;
270 }
271
272 @Override
273 public boolean acceptsURL(String u) throws SQLException {
274 return this.driver.acceptsURL(u);
275 }
276
277 @Override
278 public Connection connect(String u, Properties p) throws SQLException {
279 return this.driver.connect(u, p);
280 }
281
282 @Override
283 public int getMajorVersion() {
284 return this.driver.getMajorVersion();
285 }
286
287 @Override
288 public int getMinorVersion() {
289 return this.driver.getMinorVersion();
290 }
291
292 @Override
293 public DriverPropertyInfo[] getPropertyInfo(String u, Properties p) throws SQLException {
294 return this.driver.getPropertyInfo(u, p);
295 }
296
297 @Override
298 public boolean jdbcCompliant() {
299 return this.driver.jdbcCompliant();
300 }
301
302 @Override
303 public Logger getParentLogger() {
304 return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
305 }
306 }
307
308 @Override
309 public <T> T unwrap(Class<T> iface) throws SQLException {
310 throw new SQLException(getClass().getName() + " is not a wrapper.");
311 }
312
313 @Override
314 public boolean isWrapperFor(Class<?> iface) throws SQLException {
315 return false;
316 }
317
318 @Override
319 public Logger getParentLogger() {
320
321 return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
322 }
323
324 }