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 }