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 public Integer getDefaultNetworkTimeout() {
191 return defaultNetworkTimeout;
192 }
193
194
195
196
197
198
199
200
201 public void setDefaultNetworkTimeout(Integer defaultNetworkTimeout) {
202 this.defaultNetworkTimeout = defaultNetworkTimeout;
203 }
204
205 private Connection doGetConnection(String username, String password) throws SQLException {
206 Properties props = new Properties();
207 if (driverProperties != null) {
208 props.putAll(driverProperties);
209 }
210 if (username != null) {
211 props.setProperty("user", username);
212 }
213 if (password != null) {
214 props.setProperty("password", password);
215 }
216 return doGetConnection(props);
217 }
218
219 private Connection doGetConnection(Properties properties) throws SQLException {
220 initializeDriver();
221 Connection connection = DriverManager.getConnection(url, properties);
222 configureConnection(connection);
223 return connection;
224 }
225
226 private synchronized void initializeDriver() throws SQLException {
227 if (!registeredDrivers.containsKey(driver)) {
228 Class<?> driverType;
229 try {
230 if (driverClassLoader != null) {
231 driverType = Class.forName(driver, true, driverClassLoader);
232 } else {
233 driverType = Resources.classForName(driver);
234 }
235
236
237 Driver driverInstance = (Driver)driverType.getDeclaredConstructor().newInstance();
238 DriverManager.registerDriver(new DriverProxy(driverInstance));
239 registeredDrivers.put(driver, driverInstance);
240 } catch (Exception e) {
241 throw new SQLException("Error setting driver on UnpooledDataSource. Cause: " + e);
242 }
243 }
244 }
245
246 private void configureConnection(Connection conn) throws SQLException {
247 if (defaultNetworkTimeout != null) {
248 conn.setNetworkTimeout(Executors.newSingleThreadExecutor(), defaultNetworkTimeout);
249 }
250 if (autoCommit != null && autoCommit != conn.getAutoCommit()) {
251 conn.setAutoCommit(autoCommit);
252 }
253 if (defaultTransactionIsolationLevel != null) {
254 conn.setTransactionIsolation(defaultTransactionIsolationLevel);
255 }
256 }
257
258 private static class DriverProxy implements Driver {
259 private Driver driver;
260
261 DriverProxy(Driver d) {
262 this.driver = d;
263 }
264
265 @Override
266 public boolean acceptsURL(String u) throws SQLException {
267 return this.driver.acceptsURL(u);
268 }
269
270 @Override
271 public Connection connect(String u, Properties p) throws SQLException {
272 return this.driver.connect(u, p);
273 }
274
275 @Override
276 public int getMajorVersion() {
277 return this.driver.getMajorVersion();
278 }
279
280 @Override
281 public int getMinorVersion() {
282 return this.driver.getMinorVersion();
283 }
284
285 @Override
286 public DriverPropertyInfo[] getPropertyInfo(String u, Properties p) throws SQLException {
287 return this.driver.getPropertyInfo(u, p);
288 }
289
290 @Override
291 public boolean jdbcCompliant() {
292 return this.driver.jdbcCompliant();
293 }
294
295 @Override
296 public Logger getParentLogger() {
297 return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
298 }
299 }
300
301 @Override
302 public <T> T unwrap(Class<T> iface) throws SQLException {
303 throw new SQLException(getClass().getName() + " is not a wrapper.");
304 }
305
306 @Override
307 public boolean isWrapperFor(Class<?> iface) throws SQLException {
308 return false;
309 }
310
311 @Override
312 public Logger getParentLogger() {
313
314 return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
315 }
316
317 }