UnpooledDataSource.java

  1. /*
  2.  *    Copyright 2009-2021 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. import java.io.PrintWriter;
  18. import java.sql.Connection;
  19. import java.sql.Driver;
  20. import java.sql.DriverManager;
  21. import java.sql.DriverPropertyInfo;
  22. import java.sql.SQLException;
  23. import java.util.Enumeration;
  24. import java.util.Map;
  25. import java.util.Properties;
  26. import java.util.concurrent.ConcurrentHashMap;
  27. import java.util.concurrent.Executors;
  28. import java.util.logging.Logger;

  29. import javax.sql.DataSource;

  30. import org.apache.ibatis.io.Resources;

  31. /**
  32.  * @author Clinton Begin
  33.  * @author Eduardo Macarron
  34.  */
  35. public class UnpooledDataSource implements DataSource {

  36.   private ClassLoader driverClassLoader;
  37.   private Properties driverProperties;
  38.   private static Map<String, Driver> registeredDrivers = new ConcurrentHashMap<>();

  39.   private String driver;
  40.   private String url;
  41.   private String username;
  42.   private String password;

  43.   private Boolean autoCommit;
  44.   private Integer defaultTransactionIsolationLevel;
  45.   private Integer defaultNetworkTimeout;

  46.   static {
  47.     Enumeration<Driver> drivers = DriverManager.getDrivers();
  48.     while (drivers.hasMoreElements()) {
  49.       Driver driver = drivers.nextElement();
  50.       registeredDrivers.put(driver.getClass().getName(), driver);
  51.     }
  52.   }

  53.   public UnpooledDataSource() {
  54.   }

  55.   public UnpooledDataSource(String driver, String url, String username, String password) {
  56.     this.driver = driver;
  57.     this.url = url;
  58.     this.username = username;
  59.     this.password = password;
  60.   }

  61.   public UnpooledDataSource(String driver, String url, Properties driverProperties) {
  62.     this.driver = driver;
  63.     this.url = url;
  64.     this.driverProperties = driverProperties;
  65.   }

  66.   public UnpooledDataSource(ClassLoader driverClassLoader, String driver, String url, String username, String password) {
  67.     this.driverClassLoader = driverClassLoader;
  68.     this.driver = driver;
  69.     this.url = url;
  70.     this.username = username;
  71.     this.password = password;
  72.   }

  73.   public UnpooledDataSource(ClassLoader driverClassLoader, String driver, String url, Properties driverProperties) {
  74.     this.driverClassLoader = driverClassLoader;
  75.     this.driver = driver;
  76.     this.url = url;
  77.     this.driverProperties = driverProperties;
  78.   }

  79.   @Override
  80.   public Connection getConnection() throws SQLException {
  81.     return doGetConnection(username, password);
  82.   }

  83.   @Override
  84.   public Connection getConnection(String username, String password) throws SQLException {
  85.     return doGetConnection(username, password);
  86.   }

  87.   @Override
  88.   public void setLoginTimeout(int loginTimeout) {
  89.     DriverManager.setLoginTimeout(loginTimeout);
  90.   }

  91.   @Override
  92.   public int getLoginTimeout() {
  93.     return DriverManager.getLoginTimeout();
  94.   }

  95.   @Override
  96.   public void setLogWriter(PrintWriter logWriter) {
  97.     DriverManager.setLogWriter(logWriter);
  98.   }

  99.   @Override
  100.   public PrintWriter getLogWriter() {
  101.     return DriverManager.getLogWriter();
  102.   }

  103.   public ClassLoader getDriverClassLoader() {
  104.     return driverClassLoader;
  105.   }

  106.   public void setDriverClassLoader(ClassLoader driverClassLoader) {
  107.     this.driverClassLoader = driverClassLoader;
  108.   }

  109.   public Properties getDriverProperties() {
  110.     return driverProperties;
  111.   }

  112.   public void setDriverProperties(Properties driverProperties) {
  113.     this.driverProperties = driverProperties;
  114.   }

  115.   public synchronized String getDriver() {
  116.     return driver;
  117.   }

  118.   public synchronized void setDriver(String driver) {
  119.     this.driver = driver;
  120.   }

  121.   public String getUrl() {
  122.     return url;
  123.   }

  124.   public void setUrl(String url) {
  125.     this.url = url;
  126.   }

  127.   public String getUsername() {
  128.     return username;
  129.   }

  130.   public void setUsername(String username) {
  131.     this.username = username;
  132.   }

  133.   public String getPassword() {
  134.     return password;
  135.   }

  136.   public void setPassword(String password) {
  137.     this.password = password;
  138.   }

  139.   public Boolean isAutoCommit() {
  140.     return autoCommit;
  141.   }

  142.   public void setAutoCommit(Boolean autoCommit) {
  143.     this.autoCommit = autoCommit;
  144.   }

  145.   public Integer getDefaultTransactionIsolationLevel() {
  146.     return defaultTransactionIsolationLevel;
  147.   }

  148.   public void setDefaultTransactionIsolationLevel(Integer defaultTransactionIsolationLevel) {
  149.     this.defaultTransactionIsolationLevel = defaultTransactionIsolationLevel;
  150.   }

  151.   /**
  152.    * Gets the default network timeout.
  153.    *
  154.    * @return the default network timeout
  155.    * @since 3.5.2
  156.    */
  157.   public Integer getDefaultNetworkTimeout() {
  158.     return defaultNetworkTimeout;
  159.   }

  160.   /**
  161.    * Sets the default network timeout value to wait for the database operation to complete. See {@link Connection#setNetworkTimeout(java.util.concurrent.Executor, int)}
  162.    *
  163.    * @param defaultNetworkTimeout
  164.    *          The time in milliseconds to wait for the database operation to complete.
  165.    * @since 3.5.2
  166.    */
  167.   public void setDefaultNetworkTimeout(Integer defaultNetworkTimeout) {
  168.     this.defaultNetworkTimeout = defaultNetworkTimeout;
  169.   }

  170.   private Connection doGetConnection(String username, String password) throws SQLException {
  171.     Properties props = new Properties();
  172.     if (driverProperties != null) {
  173.       props.putAll(driverProperties);
  174.     }
  175.     if (username != null) {
  176.       props.setProperty("user", username);
  177.     }
  178.     if (password != null) {
  179.       props.setProperty("password", password);
  180.     }
  181.     return doGetConnection(props);
  182.   }

  183.   private Connection doGetConnection(Properties properties) throws SQLException {
  184.     initializeDriver();
  185.     Connection connection = DriverManager.getConnection(url, properties);
  186.     configureConnection(connection);
  187.     return connection;
  188.   }

  189.   private synchronized void initializeDriver() throws SQLException {
  190.     if (!registeredDrivers.containsKey(driver)) {
  191.       Class<?> driverType;
  192.       try {
  193.         if (driverClassLoader != null) {
  194.           driverType = Class.forName(driver, true, driverClassLoader);
  195.         } else {
  196.           driverType = Resources.classForName(driver);
  197.         }
  198.         // DriverManager requires the driver to be loaded via the system ClassLoader.
  199.         // http://www.kfu.com/~nsayer/Java/dyn-jdbc.html
  200.         Driver driverInstance = (Driver) driverType.getDeclaredConstructor().newInstance();
  201.         DriverManager.registerDriver(new DriverProxy(driverInstance));
  202.         registeredDrivers.put(driver, driverInstance);
  203.       } catch (Exception e) {
  204.         throw new SQLException("Error setting driver on UnpooledDataSource. Cause: " + e);
  205.       }
  206.     }
  207.   }

  208.   private void configureConnection(Connection conn) throws SQLException {
  209.     if (defaultNetworkTimeout != null) {
  210.       conn.setNetworkTimeout(Executors.newSingleThreadExecutor(), defaultNetworkTimeout);
  211.     }
  212.     if (autoCommit != null && autoCommit != conn.getAutoCommit()) {
  213.       conn.setAutoCommit(autoCommit);
  214.     }
  215.     if (defaultTransactionIsolationLevel != null) {
  216.       conn.setTransactionIsolation(defaultTransactionIsolationLevel);
  217.     }
  218.   }

  219.   private static class DriverProxy implements Driver {
  220.     private Driver driver;

  221.     DriverProxy(Driver d) {
  222.       this.driver = d;
  223.     }

  224.     @Override
  225.     public boolean acceptsURL(String u) throws SQLException {
  226.       return this.driver.acceptsURL(u);
  227.     }

  228.     @Override
  229.     public Connection connect(String u, Properties p) throws SQLException {
  230.       return this.driver.connect(u, p);
  231.     }

  232.     @Override
  233.     public int getMajorVersion() {
  234.       return this.driver.getMajorVersion();
  235.     }

  236.     @Override
  237.     public int getMinorVersion() {
  238.       return this.driver.getMinorVersion();
  239.     }

  240.     @Override
  241.     public DriverPropertyInfo[] getPropertyInfo(String u, Properties p) throws SQLException {
  242.       return this.driver.getPropertyInfo(u, p);
  243.     }

  244.     @Override
  245.     public boolean jdbcCompliant() {
  246.       return this.driver.jdbcCompliant();
  247.     }

  248.     @Override
  249.     public Logger getParentLogger() {
  250.       return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
  251.     }
  252.   }

  253.   @Override
  254.   public <T> T unwrap(Class<T> iface) throws SQLException {
  255.     throw new SQLException(getClass().getName() + " is not a wrapper.");
  256.   }

  257.   @Override
  258.   public boolean isWrapperFor(Class<?> iface) throws SQLException {
  259.     return false;
  260.   }

  261.   @Override
  262.   public Logger getParentLogger() {
  263.     // requires JDK version 1.6
  264.     return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
  265.   }

  266. }