/* * Copyright (c) 1999 Dustin Sallings <dustin@spy.net> */ package net.spy.db; import java.io.Closeable; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.StringTokenizer; import net.spy.SpyObject; import net.spy.util.SpyConfig; /** * SpyDB is an abstraction of both net.spy.pool and java.sql. */ public class SpyDB extends SpyObject implements Closeable { // The actual database connection from the PooledObject. private Connection conn; // Our configuration. private SpyConfig conf; // Is this thing closed? private boolean isClosed=false; // The connection source. private ConnectionSource source; // Exceptions that occur during initialization. private DBInitException initializationException; /** * Initialization type for SpyDB initialized from a config. */ protected static final int INIT_FROM_CONFIG=1; /** * Initialization type for SpyDB initialized from a Connection. */ protected static final int INIT_FROM_CONN=2; private final int initType; /** * Create a SpyDB object based on the description found in the passed * in SpyConfig object. * * <p> * * The configuration may vary greatly depending on the connector. The * only configuration option for SpyDB itself is * <i>dbConnectionSource</i> which specifies the name of the class that * implements {@link ConnectionSource} that will be providing * connections for this SpyDB instance. The default is * {@link net.spy.db.ObjectPoolConnectionSource net.spy.db.ObjectPoolConnectionSource}. * You will also need to provide any additional parameters that are * required by the ConnectionSource in this config. * * @param c SpyConfig object describing how to connect. */ public SpyDB(SpyConfig c) { super(); this.conf=c; initType=INIT_FROM_CONFIG; source=ConnectionSourceFactory.getInstance().getConnectionSource(c); init(); } /** * Get a SpyDB object wrapping the given connection. * * @param c the connection to wrap. */ public SpyDB(Connection c) { super(); this.conn=c; initType=INIT_FROM_CONN; init(); } /** * Get the type of initialization that created this object. * * @return either INIT_FROM_CONFIG or INIT_FROM_CONN */ public int getInitType() { return(initType); } /** * Execute a query and return a resultset, will establish a database * connection if necessary. * * @param query SQL query to execute. * * @exception SQLException an exception is thrown if the connection fails, * or the SQL query fails. */ public ResultSet executeQuery(String query) throws SQLException { Connection c=getConn(); Statement st = c.createStatement(); ResultSet rs = st.executeQuery(query); return(rs); } /** * Execute a query that doesn't return a ResultSet, such as an update, * delete, or insert. * * @param query SQL query to execute. * * @exception SQLException an exception is thrown if the connection fails, * or the SQL query fails. */ public int executeUpdate(String query) throws SQLException { int rv=0; Connection c=getConn(); Statement st = c.createStatement(); rv=st.executeUpdate(query); return(rv); } /** * Prepare a statement. * * @param query SQL query to prepare. * * @exception SQLException thrown if something bad happens. */ public PreparedStatement prepareStatement(String query) throws SQLException { Connection c=getConn(); PreparedStatement pst = c.prepareStatement(query); return(pst); } /** * Prepare a callable statement. * * @param query SQL query to prepare for call. * * @exception SQLException thrown if something bad happens. */ public CallableStatement prepareCall(String query) throws SQLException { Connection c=getConn(); CallableStatement cst = c.prepareCall(query); return(cst); } /** * Get a connection out of the pool. A given SpyDB object can only * maintain a single database connection, so if multiple connections * from the pool are needed, multiple SpyDB objects will be required. * * @exception SQLException An exception may be thrown if a database * connection cannot be obtained. */ public Connection getConn() throws SQLException { if(conn==null) { getDBConn(); } return(conn); } /** * Free an established database connection. The connection is whatever * connection has already been instablished by this instance of the * object. If a connection has not been established, this does * nothing. */ public void freeDBConn() { // Don't touch it unless it came from a ConnectionSource if(source!=null) { // If there's a source, this came from something that will want // to hear that we're done with it. if(conn!=null) { source.returnConnection(conn); conn=null; } } isClosed=true; } /** * Free an established database connection - alias to freeDBConn() */ public void close() { freeDBConn(); } /** * Initialize SpyDB. This allows any subclasses to perform further * initialization. */ protected void init() { // Subclass initialization } // Actually dig up a DB connection private void getDBConn() throws SQLException { // Different behavior whether we're using a pool or not if(initializationException!=null) { throw initializationException; } // Get the connection from the source. conn=source.getConnection(conf); } /** * Make a string safe for usage in a SQL query, quoting apostrophies, * etc... * * @param in the string that needs to be quoted * * @return a new, quoted string */ public static String dbquoteStr(String in) { // Quick...handle null if(in == null) { return(null); } String sout = null; if(in.indexOf('\'') < 0) { sout = in; } else { StringBuilder sb=new StringBuilder(in.length()); StringTokenizer st = new StringTokenizer(in, "\'", true); while(st.hasMoreTokens()) { String part = st.nextToken(); sb.append(part); // If this is a quote, add another one if(part.equals("'")) { sb.append('\''); } } sout=sb.toString(); } return(sout); } /** * Has close() been called? */ public boolean isClosed() { return(isClosed); } /** * Get the source of connections. * * @return a ConnectionSource instance, or null if this SpyDB instance * was created from a config */ public ConnectionSource getSource() { return(source); } /** * Get the configuration from which this SpyDB was instatiated. * * @return the config, or null if the SpyDB was created from a * connection */ protected SpyConfig getConfig() { return(conf); } }