/** * Copyright 2013-2014 Guoqiang Chen, Shanghai, China. All rights reserved. * * Email: subchen@gmail.com * URL: http://subchen.github.io/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrick.dao.jdbclog; import java.sql.*; import java.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Description: Wrapper class for Jdbc Driver. * <p> * <pre><code> * DriverManagerDataSource ds = new DriverManagerDataSource(); * //ds.setDriverClassName("oracle.jdbc.driver.OracleDriver"); * ds.setDriverClassName("jetbrick.commons.jdbc.log.JdbcLogDriver"); * ds.setUrl("jdbc:oracle:thin:@localhost:1521:orcl"); * ds.setUsername("sa"); * ds.setPassword(""); * </code></pre> * <p> * This JdbcLogDriver can auto identify following drivers. * <ul> * <li>MySQL</li> * <li>Oracle</li> * <li>JTDS</li> * <li>SQL Server 97/2000/2005</li> * <li>DB2</li> * <li>SyBase</li> * <li>PostgreSQL</li> * <li>HSqlDB</li> * <li>Derby</li> * <li>Informix</li> * <li>TimesTen</li> * <li>IBM-AS400</li> * <li>SAP DB</li> * <li>InterBase</li> * <li>JDBC-ODBC</li> * </ul> * * <p> * If you use other driver, you can add real driver class name into connection * url string. Pattern: CustomizeConnectionUrl = * <code>"jdbclog" ":" [DriverClassName] ":" ConnectionUrl</code>. In customize * connection url, the DriverClassName is optional. * <p> * For Oracle: * <code>jdbclog:oracle.jdbc.driver.OracleDriver:jdbc:oracle:thin:@localhost:1521:orcl</code> * <p> * If you use <code>Jdbc Odbc Bridge</code> or <code>Apache Derby</code>, you must use * customize connection url. * <p> * For Derby: * <code>jdbclog::jdbc:derby:MyDB;user=test;password=test</code> */ public final class JdbcLogDriver implements Driver { private static final Logger log = LoggerFactory.getLogger(JdbcLogDriver.class); private static final String CONNECTION_URL_SUFFIX = "jdbclog:"; private final Map<String, Driver> drivers = new HashMap<String, Driver>(8); static { try { DriverManager.registerDriver(new JdbcLogDriver()); } catch (SQLException e) { log.error("DriverManager.registerDriver Exception.", e); } } /** * url pattern = "JdbcLog" ":" [DriverClassName] ":" ConnectionUrl */ private String getDriverClassName(String url) { String driverClassName = null; if (url.startsWith(CONNECTION_URL_SUFFIX)) { url = url.substring(CONNECTION_URL_SUFFIX.length()); driverClassName = url.substring(0, url.indexOf(":")); if (driverClassName.length() > 0) { return driverClassName; } url = url.substring(url.indexOf(":") + 1); } if (url.startsWith("jdbc:oracle:thin:")) { driverClassName = "oracle.jdbc.driver.OracleDriver"; } else if (url.startsWith("jdbc:mysql:")) { driverClassName = "com.mysql.jdbc.Driver"; } else if (url.startsWith("jdbc:jtds:")) { // SQL Server or SyBase driverClassName = "net.sourceforge.jtds.jdbc.Driver"; } else if (url.startsWith("jdbc:db2:")) { driverClassName = "com.ibm.db2.jdbc.net.DB2Driver"; } else if (url.startsWith("jdbc:microsoft:sqlserver:")) { // SQL Server 7.0/2000 driverClassName = "com.microsoft.jdbc.sqlserver.SQLServerDriver"; } else if (url.startsWith("jdbc:sqlserver:")) { // SQL Server 2005 driverClassName = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; } else if (url.startsWith("jdbc:postgresql:")) { driverClassName = "org.postgresql.Driver"; } else if (url.startsWith("jdbc:hsqldb:")) { driverClassName = "org.hsqldb.jdbcDriver"; } else if (url.startsWith("jdbc:derby://")) { driverClassName = "org.apache.derby.jdbc.ClientDriver"; } else if (url.startsWith("jdbc:derby:")) { driverClassName = "org.apache.derby.jdbc.EmbeddedDriver"; } else if (url.startsWith("jdbc:sybase:Tds:")) { driverClassName = "com.sybase.jdbc.SybDriver"; } else if (url.startsWith("jdbc:informix-sqli:")) { driverClassName = "com.informix.jdbc.IfxDriver"; } else if (url.startsWith("jdbc:odbc:")) { driverClassName = "sun.jdbc.odbc.JdbcOdbcDriver"; } else if (url.startsWith("jdbc:timesten:client:")) { driverClassName = "com.timesten.jdbc.TimesTenDriver"; } else if (url.startsWith("jdbc:as400:")) { driverClassName = "com.ibm.as400.access.AS400JDBCDriver"; } else if (url.startsWith("jdbc:sapdb:")) { driverClassName = "com.sap.dbtech.jdbc.DriverSapDB"; } else if (url.startsWith("jdbc:interbase:")) { driverClassName = "interbase.interclient.Driver"; } return driverClassName; } private String getConnectionUrl(String url) { if (url.startsWith(CONNECTION_URL_SUFFIX)) { url = url.substring(CONNECTION_URL_SUFFIX.length()); url = url.substring(url.indexOf(":") + 1); } return url; } private Driver getJdbcDriver(String url) { Driver driver = drivers.get(url); if (driver == null) { String driverClassName = getDriverClassName(url); String connectionUrl = getConnectionUrl(url); log.info("driverClassName = {}", driverClassName); log.info("connectionUrl = {}", connectionUrl); try { driver = (Driver) Class.forName(driverClassName).newInstance(); } catch (Exception e) { throw new IllegalStateException(e); } drivers.put(url, driver); } return driver; } @Override public boolean acceptsURL(String url) throws SQLException { Driver driver = getJdbcDriver(url); String connectionUrl = getConnectionUrl(url); return driver.acceptsURL(connectionUrl); } @Override public Connection connect(String url, Properties info) throws SQLException { Driver driver = getJdbcDriver(url); String connectionUrl = getConnectionUrl(url); log.info("JdbcLogDriver.connect = {}", driver.getClass()); Connection conn = driver.connect(connectionUrl, info); return JdbcLogConnection.getInstance(conn); } @Override public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { Driver driver = getJdbcDriver(url); String connectionUrl = getConnectionUrl(url); return driver.getPropertyInfo(connectionUrl, info); } @Override public int getMajorVersion() { if (drivers.size() == 1) { return getFirstDriver().getMajorVersion(); } return 0; } @Override public int getMinorVersion() { if (drivers.size() == 1) { return getFirstDriver().getMinorVersion(); } return 0; } @Override public boolean jdbcCompliant() { if (drivers.size() == 1) { return getFirstDriver().jdbcCompliant(); } return false; } // JDK 1.7 @Override public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { if (drivers.size() == 1) { return getFirstDriver().getParentLogger(); } return null; } private Driver getFirstDriver() { return drivers.values().iterator().next(); } }