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