All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.javasimon.jdbc.Driver Maven / Gradle / Ivy

The newest version!
package org.javasimon.jdbc;

import org.javasimon.SimonManager;
import org.javasimon.Callback;
import org.javasimon.jdbc.logging.LoggingCallback;

import java.sql.SQLException;
import java.sql.DriverPropertyInfo;
import java.sql.DriverManager;
import java.sql.Connection;
import java.util.Properties;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.InputStream;

/**
 * Simon JDBC Proxy Driver.
 * 

* An application should not use this class directly. The application (if standalone) * should use {@link java.sql.DriverManager} only. For example: *

*
 * Connection conn = DriverManager.getConnection("jdbc:simon:oracle:thin:...", "scott", "tiger");
*

* Simon driver has following format of JDBC connection string: *

{@literal
 * jdbc:simon:;=;...}
* Simon driver recognizes two parameters: *
    *
  • * {@code SIMON_REAL_DRV} - if you don't want or can't register real driver for any * reason, you can use this parameter and Simon proxy driver will do the registration * for you. You don't need to specify real driver parameter for some well known databases. * Simon proxy driver recognize database by first key word after JDBC and register. *
  • *
  • * {@code SIMON_PREFIX} - setting this parameter you can choose different prefix * for all monitors for one instance of driver. For example, setting * {@code SIMON_PREFIX=com.foo} will ensure that all proxy related Simons are located * under the subtree specified by the prefix, e.g. {@code com.foo.conn}, com.foo.stmt, * com.foo.select, etc. If no prefix is set, default {@code org.javasimon.jdbc} prefix * is used. *
  • *
  • * {@code SIMON_LOGFILE} - setting this parameter you can enable logging events (JDBC activity) * to specified file, for example {@code ...;simon_logfile=c:\jdbc.log} or * {@code ...;simon_logfile=/tmp/jdbc.log}. *
  • *
  • * {@code SIMON_LOGGER} - setting this you can enable logging events (JDBC activity) to specified JDK14 * logger (@{link java.util.logging.Logger}), for example {@code ...;simon_logger=my.package.logger}. *
  • *
  • * {@code SIMON_CONSOLE} - setting this you can enable logging events (JDBC activity) to console, which is * ({@code System.err}) using standard {@link java.util.logging.ConsoleHandler}, for example * {@code ...;simon_console=y} or {@code ...;simon_console=true}. *
  • *
  • * {@code SIMON_FORMAT} - by this parameter you can set format of log. There are two build-in formats: * {@code human} and {@code csv}. Custom format is also possible by specifing clasname. Custom formatter * must by derived from {@link org.javasimon.jdbc.logging.SimonFormatter}. For example * {@code ...;simon_format=csv} or {@code ...;simon_format=my.package.MyFormmater} *
  • *
` *

* By default, there is no need to load any driver explicitly, because drivers are loaded automatically * (since JDK 1.5) if they are in class path and jar have appropriate * meta information (see {@link java.sql.DriverManager}). *

* If this is not a case for any reason, you need to register Simon proxy driver at least. * For real driver Simon proxy driver contains following procedure for find and register it: *

    *
  1. Simon proxy driver tries if there is registered driver for driver key word. *
  2. If not, driver tries if there is real driver parameter in info properties and then registers it. *
  3. If not, driver tries to find driver by key word within internal list of well known drivers and * then registers it. For now, list contains default drivers for Oracle, PostgreSQL, Enterprise DB, H2, * MySQL. *
  4. If not, driver tries to find real driver param within connection string and then registers it. *
  5. If not, getting new connection fails. *
* The safest way to get Simon proxy driver work is to load the drivers, the real one (i.e. oracle) * and a Simon proxy driver explicitly. This can be done using Class.forName. To load the driver and open a * database connection, use following code: *
 * Class.forName("oracle.jdbc.driver.OracleDriver");  // loads real driver
 * Class.forName("org.javasimon.jdbc.Driver");  // loads Simon proxy driver
 * Connection conn = DriverManager.getConnection(
 *      "jdbc:simon:oracle:thin:...", "scott", "tiger");
* * @author Radovan Sninsky * @version $Revision: 304 $ $Date: 2011-04-08 10:39:02 +0200 (Fri, 08 Apr 2011) $ * @see java.sql.DriverManager#getConnection(String) * @since 1.0 */ public final class Driver implements java.sql.Driver { /** * Name for the property holding the real driver class value. */ public static final String REAL_DRIVER = "simon_real_drv"; /** * Default hierarchy prefix for Simon JDBC driver. All Simons created by Simon JDBC * driver without explicitly specified prefix are started with default prefix. */ public static final String DEFAULT_PREFIX = "org.javasimon.jdbc"; /** * Name for the driver property holding the hierarchy prefix given to JDBC Simons. */ public static final String PREFIX = "simon_prefix"; /** * Name for the driver property enabling JDBC logging to specified file. */ private static final String LOGFILE = "simon_logfile"; /** * Name for the driver property enabling JDBC logging to specified JDK14 logger (@{link java.util.logging.Logger}). */ private static final String LOGGER = "simon_logger"; /** * Name for the driver property enabling JDBC logging to console ({@code System.err}) * using {@link java.util.logging.ConsoleHandler}. */ private static final String CONSOLE = "simon_console"; /** * Name for the driver property setting format for logs. There are two build-in formats: {@code human} and * {@code csv}. Custom format is also possible by specifing clasname, must by derived from * {@link org.javasimon.jdbc.logging.SimonFormatter}. */ private static final String FORMAT = "simon_format"; static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException e) { // don't know what to do yet, maybe throw RuntimeException ??? } } private final Properties drivers = new Properties(); /** * Class Url represents Simon JDBC url. It parses given url and than provides getters for * driver's propreties if provided or default values. * * @author Radovan Sninsky * @version $Revision: 304 $ $Date: 2011-04-08 10:39:02 +0200 (Fri, 08 Apr 2011) $ * @since 2 */ static class Url { private static final String SIMON_JDBC = "jdbc:simon"; private static final int JDBC_URL_FIXED_PREFIX_LEN = 5; private String realUrl; private String driverId; private String realDriver; private String prefix; private String logfile; private String logger; private String console; private String format; /** * Class constructor, parses given url and recognizes driver's properties. * * @param url given JDBC URL */ Url(String url) { int i = url.indexOf(':', JDBC_URL_FIXED_PREFIX_LEN); if (i > -1) { driverId = url.substring(JDBC_URL_FIXED_PREFIX_LEN, i - 1); } StringTokenizer st = new StringTokenizer(url, ";"); while (st.hasMoreTokens()) { String tokenPairStr = st.nextToken().trim(); String[] tokenPair = tokenPairStr.split("=", 2); String token = tokenPair[0]; String tokenValue = tokenPair.length == 2 ? tokenPair[1].trim() : null; if (tokenPairStr.startsWith("jdbc")) { realUrl = tokenPairStr.replaceFirst(SIMON_JDBC, "jdbc"); } else if (token.equalsIgnoreCase(REAL_DRIVER)) { realDriver = tokenValue; } else if (token.equalsIgnoreCase(PREFIX)) { prefix = tokenValue; } else if (token.equalsIgnoreCase(LOGFILE)) { logfile = tokenValue; } else if (token.equalsIgnoreCase(LOGGER)) { logger = tokenValue; } else if (token.equalsIgnoreCase(CONSOLE)) { console = tokenValue; } else if (token.equalsIgnoreCase(FORMAT)) { format = tokenValue; } else { realUrl += ";" + tokenPairStr; } } } /** * Returns orignal JDBC URL without any Simon stuff. * * @return original JDBC URL */ public String getRealUrl() { return realUrl; } /** * Returns driver identifier (eg. oracle, postgres, mysql, h2, etc.). * * @return driver identifier */ public String getDriverId() { return driverId; } /** * Return real driver fully classname. * * @return driver classname */ public String getRealDriver() { return realDriver; } /** * Returns prefix for hierarchy of JDBC related Simons. * * @return prefix for JDBC Simons */ public String getPrefix() { return prefix == null ? DEFAULT_PREFIX : prefix; } /** * Returns filename to log events from JDBC Simons if provided. * * @return filename */ public String getLogfile() { return logfile; } /** * Returns logger name if provided. * * @return logger name */ public String getLogger() { return logger; } /** * Returns {@code true} if driver's parameter {@code simon_console} is set to yes, * otherwise {@code false}. * * @return {@code true} log to console is enabled, otherwise {@code false} */ public boolean getConsole() { return console != null && ( console.equalsIgnoreCase("yes") || console.equalsIgnoreCase("y") || console.equalsIgnoreCase("true") || console.equalsIgnoreCase("t") || console.equalsIgnoreCase("1") ); } /** * Returns log format (build-in or custom) if specified. * * @return log format */ public String getFormat() { return format; } } /** * Class constructor. It loads well known driver list from resource file drivers.properties. */ public Driver() { try { InputStream stream = null; try { stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("org/javasimon/jdbc/drivers.properties"); drivers.load(stream); } finally { if (stream != null) { stream.close(); } } } catch (IOException e) { // log somewhere } } /** * Opens new Simon proxy driver connection associated with real connection to specified database. * * @param simonUrl JDBC connection string (i.e. jdbc:simon:h2:file:test) * @param info properties for connection * @return open connection to database or null if provided url is not accepted by this driver * @throws SQLException if there is no real driver registered/recognized or opening real connection fails * @see org.javasimon.jdbc.Driver */ public Connection connect(String simonUrl, Properties info) throws SQLException { if (!acceptsURL(simonUrl)) { return null; } Url url = new Url(simonUrl); java.sql.Driver driver = getRealDriver(url, info); // if one of three possible way of setting logging is set, than // configure Simon JDBC driver logging through JDBC logging callback if (url.getLogfile() != null || url.getLogger() != null || url.getConsole()) { // check if LoggingCallback is already registerd LoggingCallback loggingCallback = null; for (Callback c : SimonManager.callback().callbacks()) { if (c instanceof LoggingCallback) { loggingCallback = (LoggingCallback) c; break; } } // if callback is already registered do not register callback again if (loggingCallback == null) { registerLoggingCallback(url); } } return new org.javasimon.jdbc.SimonConnection(driver.connect(url.getRealUrl(), info), url.getPrefix()); } /** * Registers JDBC logging callback to Simon manager. * * @param url instance of {@link org.javasimon.jdbc.Driver.Url} * @see org.javasimon.SimonManager#callback() * @see org.javasimon.Callback#addCallback(org.javasimon.Callback) */ private void registerLoggingCallback(Url url) { LoggingCallback loggingCallback = new LoggingCallback(); loggingCallback.setPrefix(url.getPrefix()); if (url.getLogfile() != null) { loggingCallback.setLogFilename(url.getLogfile()); } if (url.getLogger() != null) { loggingCallback.setLoggerName(url.getLogger()); } if (url.getConsole()) { loggingCallback.setLogToConsole(); } if (url.getFormat() != null) { loggingCallback.setLogFormat(url.getFormat()); } SimonManager.callback().addCallback(loggingCallback); } /** * Tries to determine driver class, instantiate it and register if already not registered. * For more detail look at {@link org.javasimon.jdbc.Driver} class javadoc. * * @param url instance of url object that represents url * @param info parameters from {@link #connect(String, java.util.Properties)} method * @return instance of real driver * @throws SQLException if real driver can't be determined or is not registerd */ private java.sql.Driver getRealDriver(Url url, Properties info) throws SQLException { java.sql.Driver drv = null; try { drv = DriverManager.getDriver(url.getRealUrl()); } catch (SQLException e) { // nothing, not an error } if (drv == null && info != null && info.keySet().contains(REAL_DRIVER)) { drv = registerDriver(info.getProperty(REAL_DRIVER)); } if (drv == null && url.getDriverId() != null) { drv = registerDriver(drivers.getProperty(url.getDriverId())); } if (drv == null) { if (url.getRealDriver() != null) { drv = registerDriver(url.getRealDriver()); } } if (drv == null) { throw new SQLException("Real driver is not registered and can't determine real driver class name for registration."); } return drv; } /** * Registers real driver through {@link java.sql.DriverManager}. * * @param name real driver class name * @return instance of registered real driver * @throws SQLException if registration fails */ private java.sql.Driver registerDriver(String name) throws SQLException { try { java.sql.Driver d = (java.sql.Driver) Class.forName(name).newInstance(); DriverManager.registerDriver(d); return d; } catch (SQLException e) { throw e; } catch (Exception e) { return null; } } /** * {@inheritDoc} */ public boolean acceptsURL(String url) throws SQLException { return url != null && url.toLowerCase().startsWith(Url.SIMON_JDBC); } /** * {@inheritDoc} */ public DriverPropertyInfo[] getPropertyInfo(String s, Properties properties) throws SQLException { return new DriverPropertyInfo[0]; } /** * {@inheritDoc} */ public int getMajorVersion() { return 2; } /** * {@inheritDoc} */ public int getMinorVersion() { return 4; } /** * {@inheritDoc} */ public boolean jdbcCompliant() { return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy