View Javadoc
1   /**
2    *    Copyright 2009-2015 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
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.logging.Logger;
29  
30  import javax.sql.DataSource;
31  
32  import org.apache.ibatis.io.Resources;
33  
34  /**
35   * @author Clinton Begin
36   * @author Eduardo Macarron
37   */
38  public class UnpooledDataSource implements DataSource {
39    
40    private ClassLoader driverClassLoader;
41    private Properties driverProperties;
42    private static Map<String, Driver> registeredDrivers = new ConcurrentHashMap<String, Driver>();
43  
44    private String driver;
45    private String url;
46    private String username;
47    private String password;
48  
49    private Boolean autoCommit;
50    private Integer defaultTransactionIsolationLevel;
51  
52    static {
53      Enumeration<Driver> drivers = DriverManager.getDrivers();
54      while (drivers.hasMoreElements()) {
55        Driver driver = drivers.nextElement();
56        registeredDrivers.put(driver.getClass().getName(), driver);
57      }
58    }
59  
60    public UnpooledDataSource() {
61    }
62  
63    public UnpooledDataSource(String driver, String url, String username, String password) {
64      this.driver = driver;
65      this.url = url;
66      this.username = username;
67      this.password = password;
68    }
69  
70    public UnpooledDataSource(String driver, String url, Properties driverProperties) {
71      this.driver = driver;
72      this.url = url;
73      this.driverProperties = driverProperties;
74    }
75  
76    public UnpooledDataSource(ClassLoader driverClassLoader, String driver, String url, String username, String password) {
77      this.driverClassLoader = driverClassLoader;
78      this.driver = driver;
79      this.url = url;
80      this.username = username;
81      this.password = password;
82    }
83  
84    public UnpooledDataSource(ClassLoader driverClassLoader, String driver, String url, Properties driverProperties) {
85      this.driverClassLoader = driverClassLoader;
86      this.driver = driver;
87      this.url = url;
88      this.driverProperties = driverProperties;
89    }
90  
91    @Override
92    public Connection getConnection() throws SQLException {
93      return doGetConnection(username, password);
94    }
95  
96    @Override
97    public Connection getConnection(String username, String password) throws SQLException {
98      return doGetConnection(username, password);
99    }
100 
101   @Override
102   public void setLoginTimeout(int loginTimeout) throws SQLException {
103     DriverManager.setLoginTimeout(loginTimeout);
104   }
105 
106   @Override
107   public int getLoginTimeout() throws SQLException {
108     return DriverManager.getLoginTimeout();
109   }
110 
111   @Override
112   public void setLogWriter(PrintWriter logWriter) throws SQLException {
113     DriverManager.setLogWriter(logWriter);
114   }
115 
116   @Override
117   public PrintWriter getLogWriter() throws SQLException {
118     return DriverManager.getLogWriter();
119   }
120 
121   public ClassLoader getDriverClassLoader() {
122     return driverClassLoader;
123   }
124 
125   public void setDriverClassLoader(ClassLoader driverClassLoader) {
126     this.driverClassLoader = driverClassLoader;
127   }
128 
129   public Properties getDriverProperties() {
130     return driverProperties;
131   }
132 
133   public void setDriverProperties(Properties driverProperties) {
134     this.driverProperties = driverProperties;
135   }
136 
137   public String getDriver() {
138     return driver;
139   }
140 
141   public synchronized void setDriver(String driver) {
142     this.driver = driver;
143   }
144 
145   public String getUrl() {
146     return url;
147   }
148 
149   public void setUrl(String url) {
150     this.url = url;
151   }
152 
153   public String getUsername() {
154     return username;
155   }
156 
157   public void setUsername(String username) {
158     this.username = username;
159   }
160 
161   public String getPassword() {
162     return password;
163   }
164 
165   public void setPassword(String password) {
166     this.password = password;
167   }
168 
169   public Boolean isAutoCommit() {
170     return autoCommit;
171   }
172 
173   public void setAutoCommit(Boolean autoCommit) {
174     this.autoCommit = autoCommit;
175   }
176 
177   public Integer getDefaultTransactionIsolationLevel() {
178     return defaultTransactionIsolationLevel;
179   }
180 
181   public void setDefaultTransactionIsolationLevel(Integer defaultTransactionIsolationLevel) {
182     this.defaultTransactionIsolationLevel = defaultTransactionIsolationLevel;
183   }
184 
185   private Connection doGetConnection(String username, String password) throws SQLException {
186     Properties props = new Properties();
187     if (driverProperties != null) {
188       props.putAll(driverProperties);
189     }
190     if (username != null) {
191       props.setProperty("user", username);
192     }
193     if (password != null) {
194       props.setProperty("password", password);
195     }
196     return doGetConnection(props);
197   }
198 
199   private Connection doGetConnection(Properties properties) throws SQLException {
200     initializeDriver();
201     Connection connection = DriverManager.getConnection(url, properties);
202     configureConnection(connection);
203     return connection;
204   }
205 
206   private synchronized void initializeDriver() throws SQLException {
207     if (!registeredDrivers.containsKey(driver)) {
208       Class<?> driverType;
209       try {
210         if (driverClassLoader != null) {
211           driverType = Class.forName(driver, true, driverClassLoader);
212         } else {
213           driverType = Resources.classForName(driver);
214         }
215         // DriverManager requires the driver to be loaded via the system ClassLoader.
216         // http://www.kfu.com/~nsayer/Java/dyn-jdbc.html
217         Driver driverInstance = (Driver)driverType.newInstance();
218         DriverManager.registerDriver(new DriverProxy(driverInstance));
219         registeredDrivers.put(driver, driverInstance);
220       } catch (Exception e) {
221         throw new SQLException("Error setting driver on UnpooledDataSource. Cause: " + e);
222       }
223     }
224   }
225 
226   private void configureConnection(Connection conn) throws SQLException {
227     if (autoCommit != null && autoCommit != conn.getAutoCommit()) {
228       conn.setAutoCommit(autoCommit);
229     }
230     if (defaultTransactionIsolationLevel != null) {
231       conn.setTransactionIsolation(defaultTransactionIsolationLevel);
232     }
233   }
234 
235   private static class DriverProxy implements Driver {
236     private Driver driver;
237 
238     DriverProxy(Driver d) {
239       this.driver = d;
240     }
241 
242     @Override
243     public boolean acceptsURL(String u) throws SQLException {
244       return this.driver.acceptsURL(u);
245     }
246 
247     @Override
248     public Connection connect(String u, Properties p) throws SQLException {
249       return this.driver.connect(u, p);
250     }
251 
252     @Override
253     public int getMajorVersion() {
254       return this.driver.getMajorVersion();
255     }
256 
257     @Override
258     public int getMinorVersion() {
259       return this.driver.getMinorVersion();
260     }
261 
262     @Override
263     public DriverPropertyInfo[] getPropertyInfo(String u, Properties p) throws SQLException {
264       return this.driver.getPropertyInfo(u, p);
265     }
266 
267     @Override
268     public boolean jdbcCompliant() {
269       return this.driver.jdbcCompliant();
270     }
271 
272     // @Override only valid jdk7+
273     public Logger getParentLogger() {
274       return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
275     }
276   }
277 
278   @Override
279   public <T> T unwrap(Class<T> iface) throws SQLException {
280     throw new SQLException(getClass().getName() + " is not a wrapper.");
281   }
282 
283   @Override
284   public boolean isWrapperFor(Class<?> iface) throws SQLException {
285     return false;
286   }
287 
288   // @Override only valid jdk7+
289   public Logger getParentLogger() {
290     // requires JDK version 1.6
291     return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
292   }
293 
294 }