You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ibatis.apache.org by cb...@apache.org on 2008/08/08 01:21:58 UTC
svn commit: r683745 [17/22] - in /ibatis/trunk/java/ibatis-3: ./
ibatis-3-compat/ ibatis-3-compat/src/ ibatis-3-compat/src/main/
ibatis-3-compat/src/main/java/ ibatis-3-compat/src/main/java/com/
ibatis-3-compat/src/main/java/com/ibatis/ ibatis-3-compat...
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/jdbc/SimpleDataSource.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/jdbc/SimpleDataSource.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/jdbc/SimpleDataSource.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/jdbc/SimpleDataSource.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,1086 @@
+package org.apache.ibatis.jdbc;
+
+import org.apache.ibatis.logging.*;
+import org.apache.ibatis.reflection.ExceptionUtil;
+
+import javax.sql.DataSource;
+import java.io.PrintWriter;
+import java.lang.reflect.*;
+import java.sql.*;
+import java.util.*;
+
+/**
+ * This is a simple, synchronous, thread-safe database connection pool.
+ */
+public class SimpleDataSource implements DataSource {
+
+ private static final Log log = LogFactory.getLog(SimpleDataSource.class);
+
+ private int expectedConnectionTypeCode;
+
+ // FIELDS LOCKED BY POOL_LOCK
+ private final Object POOL_LOCK = new Object();
+ private List idleConnections = new ArrayList();
+ private List activeConnections = new ArrayList();
+ private long requestCount = 0;
+ private long accumulatedRequestTime = 0;
+ private long accumulatedCheckoutTime = 0;
+ private long claimedOverdueConnectionCount = 0;
+ private long accumulatedCheckoutTimeOfOverdueConnections = 0;
+ private long accumulatedWaitTime = 0;
+ private long hadToWaitCount = 0;
+ private long badConnectionCount = 0;
+
+ // REQUIRED CONFIGURATION FIELDS
+ private String jdbcDriver;
+ private String jdbcUrl;
+ private String jdbcUsername;
+ private String jdbcPassword;
+
+ // OPTIONAL CONFIGURATION FIELDS
+ private boolean jdbcDefaultAutoCommit = false;
+ private Properties jdbcDriverProperties;
+ private int poolMaximumActiveConnections = 10;
+ private int poolMaximumIdleConnections = 5;
+ private int poolMaximumCheckoutTime = 20000;
+ private int poolTimeToWait = 20000;
+ private String poolPingQuery = "NO PING QUERY SET";
+ private boolean poolPingEnabled = false;
+ private int poolPingConnectionsNotUsedFor = 0;
+
+ /**
+ * @see javax.sql.DataSource#getConnection()
+ */
+ public Connection getConnection() throws SQLException {
+ return popConnection(jdbcUsername, jdbcPassword).getProxyConnection();
+ }
+
+ /**
+ * @see javax.sql.DataSource#getConnection(String, String)
+ */
+ public Connection getConnection(String username, String password) throws SQLException {
+ return popConnection(username, password).getProxyConnection();
+ }
+
+ /**
+ * @see javax.sql.DataSource#setLoginTimeout(int)
+ */
+ public void setLoginTimeout(int loginTimeout) throws SQLException {
+ DriverManager.setLoginTimeout(loginTimeout);
+ }
+
+ /**
+ * @see javax.sql.DataSource#getLoginTimeout()
+ */
+ public int getLoginTimeout() throws SQLException {
+ return DriverManager.getLoginTimeout();
+ }
+
+ /**
+ * @see javax.sql.DataSource#setLogWriter(java.io.PrintWriter)
+ */
+ public void setLogWriter(PrintWriter logWriter) throws SQLException {
+ DriverManager.setLogWriter(logWriter);
+ }
+
+ /**
+ * @see javax.sql.DataSource#getLogWriter()
+ */
+ public PrintWriter getLogWriter() throws SQLException {
+ return DriverManager.getLogWriter();
+ }
+
+ /**
+ * Name of the JDBC driver class to be used.
+ *
+ * @param jdbcDriver The string name of the class
+ */
+ public void setJdbcDriver(String jdbcDriver) {
+ this.jdbcDriver = jdbcDriver;
+ try {
+ Class driverType = Class.forName(jdbcDriver);
+ DriverManager.registerDriver((Driver) driverType.newInstance());
+ } catch (Exception e) {
+ throw new RuntimeException("Error setting driver on SimpleDataSource. Cause: " + e, e);
+ }
+ forceCloseAll();
+ }
+
+ /**
+ * The JDBC URL to use.
+ *
+ * @param jdbcUrl The JDBC URL
+ */
+ public void setJdbcUrl(String jdbcUrl) {
+ this.jdbcUrl = jdbcUrl;
+ forceCloseAll();
+ }
+
+ /**
+ * The JDBC user name to use
+ *
+ * @param jdbcUsername The user name
+ */
+ public void setJdbcUsername(String jdbcUsername) {
+ this.jdbcUsername = jdbcUsername;
+ forceCloseAll();
+ }
+
+ /**
+ * The JDBC password to use
+ *
+ * @param jdbcPassword The password
+ */
+ public void setJdbcPassword(String jdbcPassword) {
+ this.jdbcPassword = jdbcPassword;
+ forceCloseAll();
+ }
+
+ /**
+ * Recommend leaving this false. Basically disables transactions if set to true.
+ *
+ * @param jdbcDefaultAutoCommit
+ */
+
+ public void setJdbcDefaultAutoCommit(boolean jdbcDefaultAutoCommit) {
+ this.jdbcDefaultAutoCommit = jdbcDefaultAutoCommit;
+ forceCloseAll();
+ }
+
+ /**
+ * Use alternate connection initializer with properties that may be specific
+ * to your driver.
+ *
+ * @param driverProps The properties for your driver
+ */
+ public void setJdbcDriverProperties(Properties driverProps) {
+ this.jdbcDriverProperties = driverProps;
+ forceCloseAll();
+ }
+
+ /**
+ * The maximum number of active connections
+ *
+ * @param poolMaximumActiveConnections The maximum number of active connections
+ */
+ public void setPoolMaximumActiveConnections(int poolMaximumActiveConnections) {
+ this.poolMaximumActiveConnections = poolMaximumActiveConnections;
+ forceCloseAll();
+ }
+
+ /**
+ * The maximum number of idle connections
+ *
+ * @param poolMaximumIdleConnections The maximum number of idle connections
+ */
+ public void setPoolMaximumIdleConnections(int poolMaximumIdleConnections) {
+ this.poolMaximumIdleConnections = poolMaximumIdleConnections;
+ forceCloseAll();
+ }
+
+ /**
+ * The maximum time a connection can be used before it *may* be
+ * given away again.
+ *
+ * @param poolMaximumCheckoutTime The maximum time
+ */
+ public void setPoolMaximumCheckoutTime(int poolMaximumCheckoutTime) {
+ this.poolMaximumCheckoutTime = poolMaximumCheckoutTime;
+ forceCloseAll();
+ }
+
+ /**
+ * The time to wait before retrying to get a connection
+ *
+ * @param poolTimeToWait The time to wait
+ */
+ public void setPoolTimeToWait(int poolTimeToWait) {
+ this.poolTimeToWait = poolTimeToWait;
+ forceCloseAll();
+ }
+
+ /**
+ * The query to be used to check a connection
+ *
+ * @param poolPingQuery The query
+ */
+ public void setPoolPingQuery(String poolPingQuery) {
+ this.poolPingQuery = poolPingQuery;
+ forceCloseAll();
+ }
+
+ /**
+ * Determines if the ping query should be used.
+ *
+ * @param poolPingEnabled True if we need to check a connection before using it
+ */
+ public void setPoolPingEnabled(boolean poolPingEnabled) {
+ this.poolPingEnabled = poolPingEnabled;
+ forceCloseAll();
+ }
+
+ /**
+ * If a connection has not been used in this many milliseconds, ping the
+ * database to make sure the connection is still good.
+ *
+ * @param milliseconds the number of milliseconds of inactivity that will trigger a ping
+ */
+ public void setPoolPingConnectionsNotUsedFor(int milliseconds) {
+ this.poolPingConnectionsNotUsedFor = milliseconds;
+ forceCloseAll();
+ }
+
+ public String getJdbcDriver() {
+ return jdbcDriver;
+ }
+
+ public String getJdbcUrl() {
+ return jdbcUrl;
+ }
+
+ public String getJdbcUsername() {
+ return jdbcUsername;
+ }
+
+ public String getJdbcPassword() {
+ return jdbcPassword;
+ }
+
+ public boolean isJdbcDefaultAutoCommit() {
+ return jdbcDefaultAutoCommit;
+ }
+
+ public Properties getJdbcDriverProperties() {
+ return jdbcDriverProperties;
+ }
+
+ public int getPoolMaximumActiveConnections() {
+ return poolMaximumActiveConnections;
+ }
+
+ public int getPoolMaximumIdleConnections() {
+ return poolMaximumIdleConnections;
+ }
+
+ public int getPoolMaximumCheckoutTime() {
+ return poolMaximumCheckoutTime;
+ }
+
+ public int getPoolTimeToWait() {
+ return poolTimeToWait;
+ }
+
+ public String getPoolPingQuery() {
+ return poolPingQuery;
+ }
+
+ public boolean isPoolPingEnabled() {
+ return poolPingEnabled;
+ }
+
+ public int getPoolPingConnectionsNotUsedFor() {
+ return poolPingConnectionsNotUsedFor;
+ }
+
+ /**
+ * Getter for the number of connection requests made
+ *
+ * @return The number of connection requests made
+ */
+ public long getRequestCount() {
+ synchronized (POOL_LOCK) {
+ return requestCount;
+ }
+ }
+
+ /**
+ * Getter for the average time required to get a connection to the database
+ *
+ * @return The average time
+ */
+ public long getAverageRequestTime() {
+ synchronized (POOL_LOCK) {
+ return requestCount == 0 ? 0 : accumulatedRequestTime / requestCount;
+ }
+ }
+
+ /**
+ * Getter for the average time spent waiting for connections that were in use
+ *
+ * @return The average time
+ */
+ public long getAverageWaitTime() {
+ synchronized (POOL_LOCK) {
+ return hadToWaitCount == 0 ? 0 : accumulatedWaitTime / hadToWaitCount;
+ }
+ }
+
+ /**
+ * Getter for the number of requests that had to wait for connections that were in use
+ *
+ * @return The number of requests that had to wait
+ */
+ public long getHadToWaitCount() {
+ synchronized (POOL_LOCK) {
+ return hadToWaitCount;
+ }
+ }
+
+ /**
+ * Getter for the number of invalid connections that were found in the pool
+ *
+ * @return The number of invalid connections
+ */
+ public long getBadConnectionCount() {
+ synchronized (POOL_LOCK) {
+ return badConnectionCount;
+ }
+ }
+
+ /**
+ * Getter for the number of connections that were claimed before they were returned
+ *
+ * @return The number of connections
+ */
+ public long getClaimedOverdueConnectionCount() {
+ synchronized (POOL_LOCK) {
+ return claimedOverdueConnectionCount;
+ }
+ }
+
+ /**
+ * Getter for the average age of overdue connections
+ *
+ * @return The average age
+ */
+ public long getAverageOverdueCheckoutTime() {
+ synchronized (POOL_LOCK) {
+ return claimedOverdueConnectionCount == 0 ? 0 : accumulatedCheckoutTimeOfOverdueConnections / claimedOverdueConnectionCount;
+ }
+ }
+
+
+ /**
+ * Getter for the average age of a connection checkout
+ *
+ * @return The average age
+ */
+ public long getAverageCheckoutTime() {
+ synchronized (POOL_LOCK) {
+ return requestCount == 0 ? 0 : accumulatedCheckoutTime / requestCount;
+ }
+ }
+
+
+ public int getIdleConnectionCount() {
+ synchronized (POOL_LOCK) {
+ return idleConnections.size();
+ }
+ }
+
+ public int getActiveConnectionCount() {
+ synchronized (POOL_LOCK) {
+ return activeConnections.size();
+ }
+ }
+
+
+ /**
+ * Returns the status of the connection pool
+ *
+ * @return The status
+ */
+ public String getStatus() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("\n===CONFINGURATION==============================================");
+ buffer.append("\n jdbcDriver ").append(jdbcDriver);
+ buffer.append("\n jdbcUrl ").append(jdbcUrl);
+ buffer.append("\n jdbcUsername ").append(jdbcUsername);
+ buffer.append("\n jdbcPassword ").append((jdbcPassword == null ? "NULL" : "************"));
+ buffer.append("\n poolMaxActiveConnections ").append(poolMaximumActiveConnections);
+ buffer.append("\n poolMaxIdleConnections ").append(poolMaximumIdleConnections);
+ buffer.append("\n poolMaxCheckoutTime ").append(poolMaximumCheckoutTime);
+ buffer.append("\n poolTimeToWait ").append(poolTimeToWait);
+ buffer.append("\n poolPingEnabled ").append(poolPingEnabled);
+ buffer.append("\n poolPingQuery ").append(poolPingQuery);
+ buffer.append("\n poolPingConnectionsNotUsedFor ").append(poolPingConnectionsNotUsedFor);
+ buffer.append("\n ---STATUS-----------------------------------------------------");
+ synchronized (POOL_LOCK) {
+ buffer.append("\n activeConnections ").append(getActiveConnectionCount());
+ buffer.append("\n idleConnections ").append(getIdleConnectionCount());
+ buffer.append("\n requestCount ").append(getRequestCount());
+ buffer.append("\n averageRequestTime ").append(getAverageRequestTime());
+ buffer.append("\n averageCheckoutTime ").append(getAverageCheckoutTime());
+ buffer.append("\n claimedOverdue ").append(getClaimedOverdueConnectionCount());
+ buffer.append("\n averageOverdueCheckoutTime ").append(getAverageOverdueCheckoutTime());
+ buffer.append("\n hadToWait ").append(getHadToWaitCount());
+ buffer.append("\n averageWaitTime ").append(getAverageWaitTime());
+ buffer.append("\n badConnectionCount ").append(getBadConnectionCount());
+ }
+ buffer.append("\n===============================================================");
+ return buffer.toString();
+ }
+
+ /**
+ * Closes all active and idle connections in the pool
+ */
+ public void forceCloseAll() {
+ synchronized (POOL_LOCK) {
+ expectedConnectionTypeCode = assembleConnectionTypeCode(jdbcUrl, jdbcUsername, jdbcPassword);
+ for (int i = activeConnections.size(); i > 0; i--) {
+ try {
+ SimplePooledConnection conn = (SimplePooledConnection) activeConnections.remove(i - 1);
+ conn.invalidate();
+
+ Connection realConn = conn.getRealConnection();
+ if (!realConn.getAutoCommit()) {
+ realConn.rollback();
+ }
+ realConn.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ for (int i = idleConnections.size(); i > 0; i--) {
+ try {
+ SimplePooledConnection conn = (SimplePooledConnection) idleConnections.remove(i - 1);
+ conn.invalidate();
+
+ Connection realConn = conn.getRealConnection();
+ if (!realConn.getAutoCommit()) {
+ realConn.rollback();
+ }
+ realConn.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("SimpleDataSource forcefully closed/removed all connections.");
+ }
+ }
+
+ private int assembleConnectionTypeCode(String url, String username, String password) {
+ return ("" + url + username + password).hashCode();
+ }
+
+ private void pushConnection(SimplePooledConnection conn)
+ throws SQLException {
+
+ synchronized (POOL_LOCK) {
+ activeConnections.remove(conn);
+ if (conn.isValid()) {
+ if (idleConnections.size() < poolMaximumIdleConnections && conn.getConnectionTypeCode() == expectedConnectionTypeCode) {
+ accumulatedCheckoutTime += conn.getCheckoutTime();
+ if (!conn.getRealConnection().getAutoCommit()) {
+ conn.getRealConnection().rollback();
+ }
+ SimplePooledConnection newConn = new SimplePooledConnection(conn.getRealConnection(), this);
+ idleConnections.add(newConn);
+ newConn.setCreatedTimestamp(conn.getCreatedTimestamp());
+ newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());
+ conn.invalidate();
+ if (log.isDebugEnabled()) {
+ log.debug("Returned connection " + newConn.getRealHashCode() + " to pool.");
+ }
+ POOL_LOCK.notifyAll();
+ } else {
+ accumulatedCheckoutTime += conn.getCheckoutTime();
+ if (!conn.getRealConnection().getAutoCommit()) {
+ conn.getRealConnection().rollback();
+ }
+ conn.getRealConnection().close();
+ if (log.isDebugEnabled()) {
+ log.debug("Closed connection " + conn.getRealHashCode() + ".");
+ }
+ conn.invalidate();
+ }
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("A bad connection (" + conn.getRealHashCode() + ") attempted to return to the pool, discarding connection.");
+ }
+ badConnectionCount++;
+ }
+ }
+ }
+
+ private SimplePooledConnection popConnection(String username, String password)
+ throws SQLException {
+ boolean countedWait = false;
+ SimplePooledConnection conn = null;
+ long t = System.currentTimeMillis();
+ int localBadConnectionCount = 0;
+
+ while (conn == null) {
+ synchronized (POOL_LOCK) {
+ if (idleConnections.size() > 0) {
+ // Pool has available connection
+ conn = (SimplePooledConnection) idleConnections.remove(0);
+ if (log.isDebugEnabled()) {
+ log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
+ }
+ } else {
+ // Pool does not have available connection
+ if (activeConnections.size() < poolMaximumActiveConnections) {
+ // Can create new connection
+ if (jdbcDriverProperties != null) {
+ jdbcDriverProperties.put("user", jdbcUsername);
+ jdbcDriverProperties.put("password", jdbcPassword);
+ conn = new SimplePooledConnection(DriverManager.getConnection(jdbcUrl, jdbcDriverProperties), this);
+ } else {
+ conn = new SimplePooledConnection(DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword), this);
+ }
+ Connection realConn = conn.getRealConnection();
+ if (realConn.getAutoCommit() != jdbcDefaultAutoCommit) {
+ realConn.setAutoCommit(jdbcDefaultAutoCommit);
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("Created connection " + conn.getRealHashCode() + ".");
+ }
+ } else {
+ // Cannot create new connection
+ SimplePooledConnection oldestActiveConnection = (SimplePooledConnection) activeConnections.get(0);
+ long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
+ if (longestCheckoutTime > poolMaximumCheckoutTime) {
+ // Can claim overdue connection
+ claimedOverdueConnectionCount++;
+ accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
+ accumulatedCheckoutTime += longestCheckoutTime;
+ activeConnections.remove(oldestActiveConnection);
+ if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
+ oldestActiveConnection.getRealConnection().rollback();
+ }
+ conn = new SimplePooledConnection(oldestActiveConnection.getRealConnection(), this);
+ oldestActiveConnection.invalidate();
+ if (log.isDebugEnabled()) {
+ log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
+ }
+ } else {
+ // Must wait
+ try {
+ if (!countedWait) {
+ hadToWaitCount++;
+ countedWait = true;
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection.");
+ }
+ long wt = System.currentTimeMillis();
+ POOL_LOCK.wait(poolTimeToWait);
+ accumulatedWaitTime += System.currentTimeMillis() - wt;
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
+ }
+ }
+ if (conn != null) {
+ if (conn.isValid()) {
+ if (!conn.getRealConnection().getAutoCommit()) {
+ conn.getRealConnection().rollback();
+ }
+ conn.setConnectionTypeCode(assembleConnectionTypeCode(jdbcUrl, username, password));
+ conn.setCheckoutTimestamp(System.currentTimeMillis());
+ conn.setLastUsedTimestamp(System.currentTimeMillis());
+ activeConnections.add(conn);
+ requestCount++;
+ accumulatedRequestTime += System.currentTimeMillis() - t;
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");
+ }
+ badConnectionCount++;
+ localBadConnectionCount++;
+ conn = null;
+ if (localBadConnectionCount > (poolMaximumIdleConnections + 3)) {
+ if (log.isDebugEnabled()) {
+ log.debug("SimpleDataSource: Could not get a good connection to the database.");
+ }
+ throw new SQLException("SimpleDataSource: Could not get a good connection to the database.");
+ }
+ }
+ }
+ }
+
+ }
+
+ if (conn == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("SimpleDataSource: Unknown severe error condition. The connection pool returned a null connection.");
+ }
+ throw new SQLException("SimpleDataSource: Unknown severe error condition. The connection pool returned a null connection.");
+ }
+
+ return conn;
+ }
+
+ /**
+ * Method to check to see if a connection is still usable
+ *
+ * @param conn - the connection to check
+ * @return True if the connection is still usable
+ */
+ private boolean pingConnection(SimplePooledConnection conn) {
+ boolean result = true;
+
+ try {
+ result = !conn.getRealConnection().isClosed();
+ } catch (SQLException e) {
+ if (log.isDebugEnabled()) {
+ log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage());
+ }
+ result = false;
+ }
+
+ if (result) {
+ if (poolPingEnabled) {
+ if (poolPingConnectionsNotUsedFor > 0 && conn.getTimeElapsedSinceLastUse() > poolPingConnectionsNotUsedFor) {
+ try {
+ if (log.isDebugEnabled()) {
+ log.debug("Testing connection " + conn.getRealHashCode() + " ...");
+ }
+ Connection realConn = conn.getRealConnection();
+ Statement statement = realConn.createStatement();
+ ResultSet rs = statement.executeQuery(poolPingQuery);
+ rs.close();
+ statement.close();
+ if (!realConn.getAutoCommit()) {
+ realConn.rollback();
+ }
+ result = true;
+ if (log.isDebugEnabled()) {
+ log.debug("Connection " + conn.getRealHashCode() + " is GOOD!");
+ }
+ } catch (Exception e) {
+ log.warn("Execution of ping query '" + poolPingQuery + "' failed: " + e.getMessage());
+ try {
+ conn.getRealConnection().close();
+ } catch (Exception e2) {
+ //ignore
+ }
+ result = false;
+ if (log.isDebugEnabled()) {
+ log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage());
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Unwraps a pooled connection to get to the 'real' connection
+ *
+ * @param conn - the pooled connection to unwrap
+ * @return The 'real' connection
+ */
+ public static Connection unwrapConnection(Connection conn) {
+ if (conn instanceof SimplePooledConnection) {
+ return ((SimplePooledConnection) conn).getRealConnection();
+ } else {
+ return conn;
+ }
+ }
+
+ protected void finalize() throws Throwable {
+ forceCloseAll();
+ }
+
+ /**
+ * ---------------------------------------------------------------------------------------
+ * SimplePooledConnection
+ * ---------------------------------------------------------------------------------------
+ */
+ private static class SimplePooledConnection implements InvocationHandler {
+
+ private static final String CLOSE = "close";
+ private static final Class[] IFACES = new Class[]{Connection.class};
+
+ private int hashCode = 0;
+ private SimpleDataSource dataSource;
+ private Connection realConnection;
+ private Connection proxyConnection;
+ private long checkoutTimestamp;
+ private long createdTimestamp;
+ private long lastUsedTimestamp;
+ private int connectionTypeCode;
+ private boolean valid;
+
+ /**
+ * Constructor for SimplePooledConnection that uses the Connection and SimpleDataSource passed in
+ *
+ * @param connection - the connection that is to be presented as a pooled connection
+ * @param dataSource - the dataSource that the connection is from
+ */
+ public SimplePooledConnection(Connection connection, SimpleDataSource dataSource) {
+ this.hashCode = connection.hashCode();
+ this.realConnection = connection;
+ this.dataSource = dataSource;
+ this.createdTimestamp = System.currentTimeMillis();
+ this.lastUsedTimestamp = System.currentTimeMillis();
+ this.valid = true;
+
+ proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), IFACES, this);
+ }
+
+ /**
+ * Invalidates the connection
+ */
+ public void invalidate() {
+ valid = false;
+ }
+
+ /**
+ * Method to see if the connection is usable
+ *
+ * @return True if the connection is usable
+ */
+ public boolean isValid() {
+ return valid && realConnection != null && dataSource.pingConnection(this);
+ }
+
+ /**
+ * Getter for the *real* connection that this wraps
+ *
+ * @return The connection
+ */
+ public Connection getRealConnection() {
+ return realConnection;
+ }
+
+ /**
+ * Getter for the proxy for the connection
+ *
+ * @return The proxy
+ */
+ public Connection getProxyConnection() {
+ return proxyConnection;
+ }
+
+ /**
+ * Gets the hashcode of the real connection (or 0 if it is null)
+ *
+ * @return The hashcode of the real connection (or 0 if it is null)
+ */
+ public int getRealHashCode() {
+ if (realConnection == null) {
+ return 0;
+ } else {
+ return realConnection.hashCode();
+ }
+ }
+
+ /**
+ * Getter for the connection type (based on url + user + password)
+ *
+ * @return The connection type
+ */
+ public int getConnectionTypeCode() {
+ return connectionTypeCode;
+ }
+
+ /**
+ * Setter for the connection type
+ *
+ * @param connectionTypeCode - the connection type
+ */
+ public void setConnectionTypeCode(int connectionTypeCode) {
+ this.connectionTypeCode = connectionTypeCode;
+ }
+
+ /**
+ * Getter for the time that the connection was created
+ *
+ * @return The creation timestamp
+ */
+ public long getCreatedTimestamp() {
+ return createdTimestamp;
+ }
+
+ /**
+ * Setter for the time that the connection was created
+ *
+ * @param createdTimestamp - the timestamp
+ */
+ public void setCreatedTimestamp(long createdTimestamp) {
+ this.createdTimestamp = createdTimestamp;
+ }
+
+ /**
+ * Getter for the time that the connection was last used
+ *
+ * @return - the timestamp
+ */
+ public long getLastUsedTimestamp() {
+ return lastUsedTimestamp;
+ }
+
+ /**
+ * Setter for the time that the connection was last used
+ *
+ * @param lastUsedTimestamp - the timestamp
+ */
+ public void setLastUsedTimestamp(long lastUsedTimestamp) {
+ this.lastUsedTimestamp = lastUsedTimestamp;
+ }
+
+ /**
+ * Getter for the time since this connection was last used
+ *
+ * @return - the time since the last use
+ */
+ public long getTimeElapsedSinceLastUse() {
+ return System.currentTimeMillis() - lastUsedTimestamp;
+ }
+
+ /**
+ * Getter for the age of the connection
+ *
+ * @return the age
+ */
+ public long getAge() {
+ return System.currentTimeMillis() - createdTimestamp;
+ }
+
+ /**
+ * Getter for the timestamp that this connection was checked out
+ *
+ * @return the timestamp
+ */
+ public long getCheckoutTimestamp() {
+ return checkoutTimestamp;
+ }
+
+ /**
+ * Setter for the timestamp that this connection was checked out
+ *
+ * @param timestamp the timestamp
+ */
+ public void setCheckoutTimestamp(long timestamp) {
+ this.checkoutTimestamp = timestamp;
+ }
+
+ /**
+ * Getter for the time that this connection has been checked out
+ *
+ * @return the time
+ */
+ public long getCheckoutTime() {
+ return System.currentTimeMillis() - checkoutTimestamp;
+ }
+
+ private Connection getValidConnection() {
+ if (!valid) {
+ throw new RuntimeException("Error accessing SimplePooledConnection. Connection is invalid.");
+ }
+ return realConnection;
+ }
+
+ public int hashCode() {
+ return hashCode;
+ }
+
+ /**
+ * Allows comparing this connection to another
+ *
+ * @param obj - the other connection to test for equality
+ * @see Object#equals(Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof SimplePooledConnection) {
+ return realConnection.hashCode() == (((SimplePooledConnection) obj).realConnection.hashCode());
+ } else if (obj instanceof Connection) {
+ return hashCode == obj.hashCode();
+ } else {
+ return false;
+ }
+ }
+
+ // **********************************
+ // Implemented Connection Methods -- Now handled by proxy
+ // **********************************
+
+ /**
+ * Required for InvocationHandler implementation.
+ *
+ * @param proxy - not used
+ * @param method - the method to be executed
+ * @param args - the parameters to be passed to the method
+ * @see java.lang.reflect.InvocationHandler#invoke(Object, java.lang.reflect.Method, Object[])
+ */
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ String methodName = method.getName();
+ if (CLOSE.hashCode() == methodName.hashCode() && CLOSE.equals(methodName)) {
+ dataSource.pushConnection(this);
+ return null;
+ } else {
+ try {
+ return method.invoke(getValidConnection(), args);
+ } catch (Throwable t) {
+ throw ExceptionUtil.unwrapThrowable(t);
+ }
+ }
+ }
+
+ public Statement createStatement() throws SQLException {
+ return getValidConnection().createStatement();
+ }
+
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ return getValidConnection().prepareStatement(sql);
+ }
+
+ public CallableStatement prepareCall(String sql) throws SQLException {
+ return getValidConnection().prepareCall(sql);
+ }
+
+ public String nativeSQL(String sql) throws SQLException {
+ return getValidConnection().nativeSQL(sql);
+ }
+
+ public void setAutoCommit(boolean autoCommit) throws SQLException {
+ getValidConnection().setAutoCommit(autoCommit);
+ }
+
+ public boolean getAutoCommit() throws SQLException {
+ return getValidConnection().getAutoCommit();
+ }
+
+ public void commit() throws SQLException {
+ getValidConnection().commit();
+ }
+
+ public void rollback() throws SQLException {
+ getValidConnection().rollback();
+ }
+
+ public void close() throws SQLException {
+ dataSource.pushConnection(this);
+ }
+
+ public boolean isClosed() throws SQLException {
+ return getValidConnection().isClosed();
+ }
+
+ public DatabaseMetaData getMetaData() throws SQLException {
+ return getValidConnection().getMetaData();
+ }
+
+ public void setReadOnly(boolean readOnly) throws SQLException {
+ getValidConnection().setReadOnly(readOnly);
+ }
+
+ public boolean isReadOnly() throws SQLException {
+ return getValidConnection().isReadOnly();
+ }
+
+ public void setCatalog(String catalog) throws SQLException {
+ getValidConnection().setCatalog(catalog);
+ }
+
+ public String getCatalog() throws SQLException {
+ return getValidConnection().getCatalog();
+ }
+
+ public void setTransactionIsolation(int level) throws SQLException {
+ getValidConnection().setTransactionIsolation(level);
+ }
+
+ public int getTransactionIsolation() throws SQLException {
+ return getValidConnection().getTransactionIsolation();
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ return getValidConnection().getWarnings();
+ }
+
+ public void clearWarnings() throws SQLException {
+ getValidConnection().clearWarnings();
+ }
+
+ public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+ return getValidConnection().createStatement(resultSetType, resultSetConcurrency);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ return getValidConnection().prepareCall(sql, resultSetType, resultSetConcurrency);
+ }
+
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ return getValidConnection().prepareCall(sql, resultSetType, resultSetConcurrency);
+ }
+
+ public Map getTypeMap() throws SQLException {
+ return getValidConnection().getTypeMap();
+ }
+
+ public void setTypeMap(Map map) throws SQLException {
+ getValidConnection().setTypeMap(map);
+ }
+
+ // **********************************
+ // JDK 1.4 JDBC 3.0 Methods below
+ // **********************************
+
+ public void setHoldability(int holdability) throws SQLException {
+ getValidConnection().setHoldability(holdability);
+ }
+
+ public int getHoldability() throws SQLException {
+ return getValidConnection().getHoldability();
+ }
+
+ public Savepoint setSavepoint() throws SQLException {
+ return getValidConnection().setSavepoint();
+ }
+
+ public Savepoint setSavepoint(String name) throws SQLException {
+ return getValidConnection().setSavepoint(name);
+ }
+
+ public void rollback(Savepoint savepoint) throws SQLException {
+ getValidConnection().rollback(savepoint);
+ }
+
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+ getValidConnection().releaseSavepoint(savepoint);
+ }
+
+ public Statement createStatement(int resultSetType, int resultSetConcurrency,
+ int resultSetHoldability) throws SQLException {
+ return getValidConnection().createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ return getValidConnection().prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ public CallableStatement prepareCall(String sql, int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability) throws SQLException {
+ return getValidConnection().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
+ throws SQLException {
+ return getValidConnection().prepareStatement(sql, autoGeneratedKeys);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int columnIndexes[])
+ throws SQLException {
+ return getValidConnection().prepareStatement(sql, columnIndexes);
+ }
+
+ public PreparedStatement prepareStatement(String sql, String columnNames[])
+ throws SQLException {
+ return getValidConnection().prepareStatement(sql, columnNames);
+ }
+
+
+ }
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/Log.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/Log.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/Log.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/Log.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,15 @@
+package org.apache.ibatis.logging;
+
+public interface Log {
+
+ boolean isDebugEnabled();
+
+ void error(String s, Throwable e);
+
+ void error(String s);
+
+ public void debug(String s);
+
+ public void warn(String s);
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/LogFactory.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/LogFactory.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/LogFactory.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/LogFactory.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,84 @@
+package org.apache.ibatis.logging;
+
+import java.lang.reflect.Constructor;
+
+public class LogFactory {
+
+ private static Constructor logConstructor;
+
+ static {
+ tryImplementation(new Runnable() {
+ public void run() {
+ useCommonsLogging();
+ }
+ });
+ tryImplementation(new Runnable() {
+ public void run() {
+ useLog4JLogging();
+ }
+ });
+ tryImplementation(new Runnable() {
+ public void run() {
+ useJdkLogging();
+ }
+ });
+ tryImplementation(new Runnable() {
+ public void run() {
+ useNoLogging();
+ }
+ });
+ }
+
+ public static Log getLog(Class aClass) {
+ try {
+ return (Log) logConstructor.newInstance(new Object[]{aClass});
+ } catch (Throwable t) {
+ throw new RuntimeException("Error creating logger for class " + aClass + ". Cause: " + t, t);
+ }
+ }
+
+ public static synchronized void useCommonsLogging() {
+ setImplementation("org.apache.commons.logging.LogFactory", "org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl");
+ }
+
+ public static synchronized void useLog4JLogging() {
+ setImplementation("org.apache.log4j.Logger", "org.apache.ibatis.logging.log4j.Log4jImpl");
+ }
+
+ public static synchronized void useJdkLogging() {
+ setImplementation("java.util.logging.Logger", "org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl");
+ }
+
+ public static synchronized void useStdOutLogging() {
+ setImplementation("org.apache.ibatis.logging.stdout.StdOutImpl");
+ }
+
+ public static synchronized void useNoLogging() {
+ setImplementation("org.apache.ibatis.logging.nologging.NoLoggingImpl");
+ }
+
+ private static void tryImplementation(Runnable runnable) {
+ if (logConstructor == null) {
+ try {
+ runnable.run();
+ } catch (Throwable t) {
+ //ignore
+ }
+ }
+ }
+
+ private static void setImplementation(String implClassName) {
+ setImplementation(implClassName, implClassName);
+ }
+
+ private static void setImplementation(String testClassName, String implClassName) {
+ try {
+ Class.forName(testClassName);
+ Class implClass = Class.forName(implClassName);
+ logConstructor = implClass.getConstructor(new Class[]{Class.class});
+ } catch (Throwable t) {
+ throw new RuntimeException("Error setting Log implementation. Cause: " + t, t);
+ }
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/commons/JakartaCommonsLoggingImpl.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/commons/JakartaCommonsLoggingImpl.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/commons/JakartaCommonsLoggingImpl.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/commons/JakartaCommonsLoggingImpl.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,33 @@
+package org.apache.ibatis.logging.commons;
+
+import org.apache.commons.logging.*;
+
+public class JakartaCommonsLoggingImpl implements org.apache.ibatis.logging.Log {
+
+ private Log log;
+
+ public JakartaCommonsLoggingImpl(Class clazz) {
+ log = LogFactory.getLog(clazz);
+ }
+
+ public boolean isDebugEnabled() {
+ return log.isDebugEnabled();
+ }
+
+ public void error(String s, Throwable e) {
+ log.error(s, e);
+ }
+
+ public void error(String s) {
+ log.error(s);
+ }
+
+ public void debug(String s) {
+ log.debug(s);
+ }
+
+ public void warn(String s) {
+ log.warn(s);
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/BaseJdbcLogger.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/BaseJdbcLogger.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/BaseJdbcLogger.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/BaseJdbcLogger.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,116 @@
+package org.apache.ibatis.logging.jdbc;
+
+import java.util.*;
+
+/**
+ * Base class for proxies to do logging
+ */
+public class BaseJdbcLogger {
+
+ protected static final Set<String> SET_METHODS = new HashSet<String>();
+ protected static final Set<String> GET_METHODS = new HashSet<String>();
+ protected static final Set<String> EXECUTE_METHODS = new HashSet<String>();
+
+ private Map<Object, Object> columnMap = new HashMap<Object, Object>();
+
+ private List<Object> columnNames = new ArrayList<Object>();
+ private List<Object> columnValues = new ArrayList<Object>();
+
+ /**
+ * Default constructor
+ */
+ public BaseJdbcLogger() {
+ }
+
+ static {
+ SET_METHODS.add("setString");
+ SET_METHODS.add("setInt");
+ SET_METHODS.add("setByte");
+ SET_METHODS.add("setShort");
+ SET_METHODS.add("setLong");
+ SET_METHODS.add("setDouble");
+ SET_METHODS.add("setFloat");
+ SET_METHODS.add("setTimestamp");
+ SET_METHODS.add("setDate");
+ SET_METHODS.add("setTime");
+ SET_METHODS.add("setArray");
+ SET_METHODS.add("setBigDecimal");
+ SET_METHODS.add("setAsciiStream");
+ SET_METHODS.add("setBinaryStream");
+ SET_METHODS.add("setBlob");
+ SET_METHODS.add("setBoolean");
+ SET_METHODS.add("setBytes");
+ SET_METHODS.add("setCharacterStream");
+ SET_METHODS.add("setClob");
+ SET_METHODS.add("setObject");
+ SET_METHODS.add("setNull");
+
+ GET_METHODS.add("getString");
+ GET_METHODS.add("getInt");
+ GET_METHODS.add("getByte");
+ GET_METHODS.add("getShort");
+ GET_METHODS.add("getLong");
+ GET_METHODS.add("getDouble");
+ GET_METHODS.add("getFloat");
+ GET_METHODS.add("getTimestamp");
+ GET_METHODS.add("getDate");
+ GET_METHODS.add("getTime");
+ GET_METHODS.add("getArray");
+ GET_METHODS.add("getBigDecimal");
+ GET_METHODS.add("getAsciiStream");
+ GET_METHODS.add("getBinaryStream");
+ GET_METHODS.add("getBlob");
+ GET_METHODS.add("getBoolean");
+ GET_METHODS.add("getBytes");
+ GET_METHODS.add("getCharacterStream");
+ GET_METHODS.add("getClob");
+ GET_METHODS.add("getObject");
+ GET_METHODS.add("getNull");
+
+ EXECUTE_METHODS.add("execute");
+ EXECUTE_METHODS.add("executeUpdate");
+ EXECUTE_METHODS.add("executeQuery");
+
+ }
+
+ protected void setColumn(Object key, Object value) {
+ columnMap.put(key, value);
+ columnNames.add(key);
+ columnValues.add(value);
+ }
+
+ protected Object getColumn(Object key) {
+ return columnMap.get(key);
+ }
+
+ protected String getValueString() {
+ return columnValues.toString();
+ }
+
+ protected String getTypeString() {
+ List<Object> typeList = new ArrayList<Object>(columnValues.size());
+ for (Object value : columnValues) {
+ if (value == null) {
+ typeList.add("null");
+ } else {
+ typeList.add(value.getClass().getName());
+ }
+ }
+ return typeList.toString();
+ }
+
+ protected String getColumnString() {
+ return columnNames.toString();
+ }
+
+ protected void clearColumnInfo() {
+ columnMap.clear();
+ columnNames.clear();
+ columnValues.clear();
+ }
+
+ protected String removeBreakingWhitespace(String original) {
+ return original.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ');
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/ConnectionLogger.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/ConnectionLogger.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/ConnectionLogger.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/ConnectionLogger.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,73 @@
+package org.apache.ibatis.logging.jdbc;
+
+import org.apache.ibatis.logging.*;
+import org.apache.ibatis.reflection.ExceptionUtil;
+
+import java.lang.reflect.*;
+import java.sql.*;
+
+/**
+ * Connection proxy to add logging
+ */
+public class ConnectionLogger extends BaseJdbcLogger implements InvocationHandler {
+
+ private static final Log log = LogFactory.getLog(Connection.class);
+
+ private Connection connection;
+
+ private ConnectionLogger(Connection conn) {
+ super();
+ this.connection = conn;
+ if (log.isDebugEnabled()) {
+ log.debug("Connection Opened");
+ }
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] params)
+ throws Throwable {
+ try {
+ if ("prepareStatement".equals(method.getName())) {
+ PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
+ stmt = PreparedStatementLogger.newInstance(stmt, (String) params[0]);
+ return stmt;
+ } else if ("prepareCall".equals(method.getName())) {
+ PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
+ stmt = PreparedStatementLogger.newInstance(stmt, (String) params[0]);
+ return stmt;
+ } else if ("createStatement".equals(method.getName())) {
+ Statement stmt = (Statement) method.invoke(connection, params);
+ stmt = StatementLogger.newInstance(stmt);
+ return stmt;
+ } else {
+ return method.invoke(connection, params);
+ }
+ } catch (Throwable t) {
+ Throwable t1 = ExceptionUtil.unwrapThrowable(t);
+ log.error("Error calling Connection." + method.getName() + ':', t1);
+ throw t1;
+ }
+
+ }
+
+ /**
+ * Creates a logging version of a connection
+ *
+ * @param conn - the original connection
+ * @return - the connection with logging
+ */
+ public static Connection newInstance(Connection conn) {
+ InvocationHandler handler = new ConnectionLogger(conn);
+ ClassLoader cl = Connection.class.getClassLoader();
+ return (Connection) Proxy.newProxyInstance(cl, new Class[]{Connection.class}, handler);
+ }
+
+ /**
+ * return the wrapped connection
+ *
+ * @return the connection
+ */
+ public Connection getConnection() {
+ return connection;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/PreparedStatementLogger.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/PreparedStatementLogger.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/PreparedStatementLogger.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/PreparedStatementLogger.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,92 @@
+package org.apache.ibatis.logging.jdbc;
+
+import org.apache.ibatis.logging.*;
+import org.apache.ibatis.reflection.ExceptionUtil;
+
+import java.lang.reflect.*;
+import java.sql.*;
+
+/**
+ * PreparedStatement proxy to add logging
+ */
+public class PreparedStatementLogger extends BaseJdbcLogger implements InvocationHandler {
+
+ private static final Log log = LogFactory.getLog(PreparedStatement.class);
+
+ private PreparedStatement statement;
+ private String sql;
+
+ private PreparedStatementLogger(PreparedStatement stmt, String sql) {
+ this.statement = stmt;
+ this.sql = sql;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
+ try {
+ if (EXECUTE_METHODS.contains(method.getName())) {
+ if (log.isDebugEnabled()) {
+ log.debug("Executing Statement: " + removeBreakingWhitespace(sql));
+ log.debug("Parameter Types: " + getTypeString());
+ log.debug("Parameters: " + getValueString());
+ }
+ clearColumnInfo();
+ if ("executeQuery".equals(method.getName())) {
+ ResultSet rs = (ResultSet) method.invoke(statement, params);
+ if (rs != null) {
+ return ResultSetLogger.newInstance(rs);
+ } else {
+ return null;
+ }
+ } else {
+ return method.invoke(statement, params);
+ }
+ } else if (SET_METHODS.contains(method.getName())) {
+ if ("setNull".equals(method.getName())) {
+ setColumn(params[0], null);
+ } else {
+ setColumn(params[0], params[1]);
+ }
+ return method.invoke(statement, params);
+ } else if ("getResultSet".equals(method.getName())) {
+ ResultSet rs = (ResultSet) method.invoke(statement, params);
+ if (rs != null) {
+ return ResultSetLogger.newInstance(rs);
+ } else {
+ return null;
+ }
+ } else if ("equals".equals(method.getName())) {
+ Object ps = params[0];
+ return ps instanceof Proxy && proxy == ps;
+ } else if ("hashCode".equals(method.getName())) {
+ return proxy.hashCode();
+ } else {
+ return method.invoke(statement, params);
+ }
+ } catch (Throwable t) {
+ throw ExceptionUtil.unwrapThrowable(t);
+ }
+ }
+
+ /**
+ * Creates a logging version of a PreparedStatement
+ *
+ * @param stmt - the statement
+ * @param sql - the sql statement
+ * @return - the proxy
+ */
+ public static PreparedStatement newInstance(PreparedStatement stmt, String sql) {
+ InvocationHandler handler = new PreparedStatementLogger(stmt, sql);
+ ClassLoader cl = PreparedStatement.class.getClassLoader();
+ return (PreparedStatement) Proxy.newProxyInstance(cl, new Class[]{PreparedStatement.class, CallableStatement.class}, handler);
+ }
+
+ /**
+ * Return the wrapped prepared statement
+ *
+ * @return the PreparedStatement
+ */
+ public PreparedStatement getPreparedStatement() {
+ return statement;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/ResultSetLogger.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/ResultSetLogger.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/ResultSetLogger.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/ResultSetLogger.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,79 @@
+package org.apache.ibatis.logging.jdbc;
+
+import org.apache.ibatis.logging.*;
+import org.apache.ibatis.reflection.ExceptionUtil;
+
+import java.lang.reflect.*;
+import java.sql.ResultSet;
+
+/**
+ * ResultSet proxy to add logging
+ */
+public class ResultSetLogger extends BaseJdbcLogger implements InvocationHandler {
+
+ private static final Log log = LogFactory.getLog(ResultSet.class);
+
+ boolean first = true;
+ private ResultSet rs;
+
+ private ResultSetLogger(ResultSet rs) {
+ super();
+ this.rs = rs;
+ if (log.isDebugEnabled()) {
+ log.debug("ResultSet Returned");
+ }
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
+ try {
+ Object o = method.invoke(rs, params);
+ if (GET_METHODS.contains(method.getName())) {
+ if (params[0] instanceof String) {
+ setColumn(params[0], o);
+ // setColumn(params[0], rs.getObject((String) params[0]));
+ // } else {
+ // setColumn(params[0], rs.getObject(((Integer) params[0]).intValue()));
+ }
+ } else if ("next".equals(method.getName()) || "close".equals(method.getName())) {
+ String s = getValueString();
+ if (!"[]".equals(s)) {
+ if (first) {
+ first = false;
+ if (log.isDebugEnabled()) {
+ log.debug("Columns: " + getColumnString());
+ }
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("Row: " + s);
+ }
+ }
+ clearColumnInfo();
+ }
+ return o;
+ } catch (Throwable t) {
+ throw ExceptionUtil.unwrapThrowable(t);
+ }
+ }
+
+ /**
+ * Creates a logging version of a ResultSet
+ *
+ * @param rs - the ResultSet to proxy
+ * @return - the ResultSet with logging
+ */
+ public static ResultSet newInstance(ResultSet rs) {
+ InvocationHandler handler = new ResultSetLogger(rs);
+ ClassLoader cl = ResultSet.class.getClassLoader();
+ return (ResultSet) Proxy.newProxyInstance(cl, new Class[]{ResultSet.class}, handler);
+ }
+
+ /**
+ * Get the wrapped result set
+ *
+ * @return the resultSet
+ */
+ public ResultSet getRs() {
+ return rs;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/StatementLogger.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/StatementLogger.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/StatementLogger.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdbc/StatementLogger.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,80 @@
+package org.apache.ibatis.logging.jdbc;
+
+import org.apache.ibatis.logging.*;
+import org.apache.ibatis.reflection.ExceptionUtil;
+
+import java.lang.reflect.*;
+import java.sql.*;
+
+/**
+ * Statement proxy to add logging
+ */
+public class StatementLogger extends BaseJdbcLogger implements InvocationHandler {
+
+ private static final Log log = LogFactory.getLog(Statement.class);
+
+ private Statement statement;
+
+ private StatementLogger(Statement stmt) {
+ super();
+ this.statement = stmt;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
+ try {
+ if (EXECUTE_METHODS.contains(method.getName())) {
+ if (log.isDebugEnabled()) {
+ log.debug("Statement: " + removeBreakingWhitespace((String) params[0]));
+ }
+ if ("executeQuery".equals(method.getName())) {
+ ResultSet rs = (ResultSet) method.invoke(statement, params);
+ if (rs != null) {
+ return ResultSetLogger.newInstance(rs);
+ } else {
+ return null;
+ }
+ } else {
+ return method.invoke(statement, params);
+ }
+ } else if ("getResultSet".equals(method.getName())) {
+ ResultSet rs = (ResultSet) method.invoke(statement, params);
+ if (rs != null) {
+ return ResultSetLogger.newInstance(rs);
+ } else {
+ return null;
+ }
+ } else if ("equals".equals(method.getName())) {
+ Object ps = params[0];
+ return ps instanceof Proxy && proxy == ps;
+ } else if ("hashCode".equals(method.getName())) {
+ return proxy.hashCode();
+ } else {
+ return method.invoke(statement, params);
+ }
+ } catch (Throwable t) {
+ throw ExceptionUtil.unwrapThrowable(t);
+ }
+ }
+
+ /**
+ * Creates a logging version of a Statement
+ *
+ * @param stmt - the statement
+ * @return - the proxy
+ */
+ public static Statement newInstance(Statement stmt) {
+ InvocationHandler handler = new StatementLogger(stmt);
+ ClassLoader cl = Statement.class.getClassLoader();
+ return (Statement) Proxy.newProxyInstance(cl, new Class[]{Statement.class}, handler);
+ }
+
+ /**
+ * return the wrapped statement
+ *
+ * @return the statement
+ */
+ public Statement getStatement() {
+ return statement;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdk14/Jdk14LoggingImpl.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdk14/Jdk14LoggingImpl.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdk14/Jdk14LoggingImpl.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/jdk14/Jdk14LoggingImpl.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,36 @@
+package org.apache.ibatis.logging.jdk14;
+
+import org.apache.ibatis.logging.Log;
+
+import java.util.logging.*;
+
+public class Jdk14LoggingImpl implements Log {
+
+ private Logger log;
+
+ public Jdk14LoggingImpl(Class clazz) {
+ log = Logger.getLogger(clazz.getName());
+ }
+
+ public boolean isDebugEnabled() {
+ return log.isLoggable(Level.FINE);
+ }
+
+ public void error(String s, Throwable e) {
+ log.log(Level.SEVERE, s, e);
+ }
+
+ public void error(String s) {
+ log.log(Level.SEVERE, s);
+ }
+
+ public void debug(String s) {
+ log.log(Level.FINE, s);
+ }
+
+ public void warn(String s) {
+ log.log(Level.WARNING, s);
+ }
+
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/log4j/Log4jImpl.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/log4j/Log4jImpl.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/log4j/Log4jImpl.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/log4j/Log4jImpl.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,35 @@
+package org.apache.ibatis.logging.log4j;
+
+import org.apache.ibatis.logging.Log;
+import org.apache.log4j.Logger;
+
+public class Log4jImpl implements Log {
+
+ private Logger log;
+
+ public Log4jImpl(Class clazz) {
+ log = Logger.getLogger(clazz);
+ }
+
+ public boolean isDebugEnabled() {
+ return log.isDebugEnabled();
+ }
+
+ public void error(String s, Throwable e) {
+ log.error(s, e);
+ }
+
+ public void error(String s) {
+ log.error(s);
+ }
+
+ public void debug(String s) {
+ log.debug(s);
+ }
+
+ public void warn(String s) {
+ log.warn(s);
+ }
+
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/nologging/NoLoggingImpl.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/nologging/NoLoggingImpl.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/nologging/NoLoggingImpl.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/nologging/NoLoggingImpl.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,26 @@
+package org.apache.ibatis.logging.nologging;
+
+import org.apache.ibatis.logging.Log;
+
+public class NoLoggingImpl implements Log {
+
+ public NoLoggingImpl(Class clazz) {
+ }
+
+ public boolean isDebugEnabled() {
+ return false;
+ }
+
+ public void error(String s, Throwable e) {
+ }
+
+ public void error(String s) {
+ }
+
+ public void debug(String s) {
+ }
+
+ public void warn(String s) {
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/stdout/StdOutImpl.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/stdout/StdOutImpl.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/stdout/StdOutImpl.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/logging/stdout/StdOutImpl.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,30 @@
+package org.apache.ibatis.logging.stdout;
+
+import org.apache.ibatis.logging.Log;
+
+public class StdOutImpl implements Log {
+
+ public StdOutImpl(Class clazz) {
+ }
+
+ public boolean isDebugEnabled() {
+ return true;
+ }
+
+ public void error(String s, Throwable e) {
+ System.err.println(s);
+ e.printStackTrace(System.err);
+ }
+
+ public void error(String s) {
+ System.err.println(s);
+ }
+
+ public void debug(String s) {
+ System.out.println(s);
+ }
+
+ public void warn(String s) {
+ System.out.println(s);
+ }
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/BasicSqlSource.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/BasicSqlSource.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/BasicSqlSource.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/BasicSqlSource.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,20 @@
+package org.apache.ibatis.mapping;
+
+import java.util.List;
+
+public class BasicSqlSource implements SqlSource {
+
+ private String sql;
+
+ public BasicSqlSource(String sql) {
+ this.sql = sql;
+ }
+
+ public String getSql(Object parameterObject) {
+ return sql;
+ }
+
+ public List<ParameterMapping> getParameterMappings(Object parameterObject) {
+ return null;
+ }
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/Configuration.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/Configuration.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/Configuration.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/Configuration.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,224 @@
+package org.apache.ibatis.mapping;
+
+import org.apache.ibatis.cache.Cache;
+import org.apache.ibatis.executor.*;
+import org.apache.ibatis.executor.parameter.*;
+import org.apache.ibatis.executor.result.ResultHandler;
+import org.apache.ibatis.executor.resultset.*;
+import org.apache.ibatis.executor.statement.*;
+import org.apache.ibatis.mapping.*;
+import org.apache.ibatis.plugin.*;
+import org.apache.ibatis.reflection.*;
+import org.apache.ibatis.type.*;
+
+import java.sql.Connection;
+import java.util.*;
+
+public class Configuration {
+
+ private boolean lazyLoadingEnabled = true;
+ private boolean enhancementEnabled = false;
+ private boolean multipleResultSetsEnabled = true;
+ private boolean generatedKeysEnabled = true;
+ private boolean useColumnLabel = true;
+ private boolean cacheEnabled;
+
+ //TODO: Make enum for reuse/batch/simple executors
+ private boolean statementCachingEnabled;
+ private boolean batchUpdatesEnabled;
+
+ private Properties variables = new Properties();
+ private ObjectFactory objectFactory = new DefaultObjectFactory();
+
+ private final InterceptorChain interceptorChain = new InterceptorChain();
+ private final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
+ private final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
+ private final Map<String, MappedStatement> mappedStatements = new HashMap<String, MappedStatement>();
+ private final Map<String, Cache> caches = new HashMap<String, Cache>();
+ private final Map<String, ResultMap> resultMaps = new HashMap<String, ResultMap>();
+ private final Map<String, ParameterMap> parameterMaps = new HashMap<String, ParameterMap>();
+ private Integer defaultStatementTimeout;
+
+ public boolean isLazyLoadingEnabled() {
+ return lazyLoadingEnabled;
+ }
+
+ public void setLazyLoadingEnabled(boolean lazyLoadingEnabled) {
+ this.lazyLoadingEnabled = lazyLoadingEnabled;
+ }
+
+ public boolean isEnhancementEnabled() {
+ return enhancementEnabled;
+ }
+
+ public void setEnhancementEnabled(boolean enhancementEnabled) {
+ this.enhancementEnabled = enhancementEnabled;
+ }
+
+ public boolean isMultipleResultSetsEnabled() {
+ return multipleResultSetsEnabled;
+ }
+
+ public void setMultipleResultSetsEnabled(boolean multipleResultSetsEnabled) {
+ this.multipleResultSetsEnabled = multipleResultSetsEnabled;
+ }
+
+ public boolean isGeneratedKeysEnabled() {
+ return generatedKeysEnabled;
+ }
+
+ public void setGeneratedKeysEnabled(boolean generatedKeysEnabled) {
+ this.generatedKeysEnabled = generatedKeysEnabled;
+ }
+
+ public boolean isStatementCachingEnabled() {
+ return statementCachingEnabled;
+ }
+
+ public void setStatementCachingEnabled(boolean statementCachingEnabled) {
+ this.statementCachingEnabled = statementCachingEnabled;
+ }
+
+ public boolean isBatchUpdatesEnabled() {
+ return batchUpdatesEnabled;
+ }
+
+ public void setBatchUpdatesEnabled(boolean batchUpdatesEnabled) {
+ this.batchUpdatesEnabled = batchUpdatesEnabled;
+ }
+
+ public boolean isCacheEnabled() {
+ return cacheEnabled;
+ }
+
+ public void setCacheEnabled(boolean cacheEnabled) {
+ this.cacheEnabled = cacheEnabled;
+ }
+
+ public Integer getDefaultStatementTimeout() {
+ return defaultStatementTimeout;
+ }
+
+ public void setDefaultStatementTimeout(Integer defaultStatementTimeout) {
+ this.defaultStatementTimeout = defaultStatementTimeout;
+ }
+
+ public boolean isUseColumnLabel() {
+ return useColumnLabel;
+ }
+
+ public void setUseColumnLabel(boolean useColumnLabel) {
+ this.useColumnLabel = useColumnLabel;
+ }
+
+ public Properties getVariables() {
+ return variables;
+ }
+
+ public void setVariables(Properties variables) {
+ this.variables = variables;
+ }
+
+ public TypeHandlerRegistry getTypeHandlerRegistry() {
+ return typeHandlerRegistry;
+ }
+
+ public TypeAliasRegistry getTypeAliasRegistry() {
+ return typeAliasRegistry;
+ }
+
+ public ObjectFactory getObjectFactory() {
+ return objectFactory;
+ }
+
+ public void setObjectFactory(ObjectFactory objectFactory) {
+ this.objectFactory = objectFactory;
+ }
+
+ public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject) {
+ ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject);
+ parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
+ return parameterHandler;
+ }
+
+ public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, int rowOffset, int rowLimit, ParameterHandler parameterHandler, ResultHandler resultHandler) {
+ ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, rowOffset, rowLimit, resultHandler);
+ resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
+ return resultSetHandler;
+ }
+
+ public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, int rowOffset, int rowLimit, ResultHandler resultHandler) {
+ StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowOffset, rowLimit, resultHandler);
+ statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
+ return statementHandler;
+ }
+
+ public Executor newExecutor(Connection conn) {
+ Executor executor;
+ if (batchUpdatesEnabled) {
+ executor = new BatchExecutor(conn);
+ } else if (statementCachingEnabled) {
+ executor = new ReuseExecutor(conn);
+ } else {
+ executor = new SimpleExecutor(conn);
+ }
+ if (cacheEnabled) {
+ executor = new CachingExecutor(executor);
+ }
+ executor = (Executor) interceptorChain.pluginAll(executor);
+ return executor;
+ }
+
+ public void addCache(Cache cache) {
+ caches.put(cache.getId(), cache);
+ }
+
+ public Collection<Cache> getCaches() {
+ return caches.values();
+ }
+
+ public Cache getCache(String id) {
+ return caches.get(id);
+ }
+
+ public void addResultMap(ResultMap rm) {
+ resultMaps.put(rm.getId(), rm);
+ }
+
+ public Collection<ResultMap> getResultMaps() {
+ return resultMaps.values();
+ }
+
+ public ResultMap getResultMap(String id) {
+ return resultMaps.get(id);
+ }
+
+ public void addParameterMap(ParameterMap pm) {
+ parameterMaps.put(pm.getId(), pm);
+ }
+
+ public Collection<ParameterMap> getParameterMaps() {
+ return parameterMaps.values();
+ }
+
+ public ParameterMap getParameterMap(String id) {
+ return parameterMaps.get(id);
+ }
+
+ public void addMappedStatement(MappedStatement ms) {
+ mappedStatements.put(ms.getId(), ms);
+ }
+
+ public Collection<MappedStatement> getMappedStatements() {
+ return mappedStatements.values();
+ }
+
+ public MappedStatement getMappedStatement(String id) {
+ return mappedStatements.get(id);
+ }
+
+ public void addInterceptor(Interceptor interceptor) {
+ interceptorChain.addInterceptor(interceptor);
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/Discriminator.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/Discriminator.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/Discriminator.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/Discriminator.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,43 @@
+package org.apache.ibatis.mapping;
+
+import java.util.*;
+
+public class Discriminator {
+
+ private ResultMapping resultMapping;
+ private Map<String, String> discriminatorMap;
+
+ private Discriminator() {
+ }
+
+ public static class Builder {
+ private Discriminator discriminator = new Discriminator();
+
+ public Builder(ResultMapping resultMapping, Map<String, String> discriminatorMap) {
+ discriminator.resultMapping = resultMapping;
+ discriminator.discriminatorMap = discriminatorMap;
+ }
+
+ public Discriminator build() {
+ assert discriminator.resultMapping != null;
+ assert discriminator.discriminatorMap != null;
+ assert discriminator.discriminatorMap.size() > 0;
+ //lock down map
+ discriminator.discriminatorMap = Collections.unmodifiableMap(discriminator.discriminatorMap);
+ return discriminator;
+ }
+ }
+
+ public ResultMapping getResultMapping() {
+ return resultMapping;
+ }
+
+ public Map<String, String> getDiscriminatorMap() {
+ return discriminatorMap;
+ }
+
+ public String getMapIdFor(String s) {
+ return discriminatorMap.get(s);
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/MappedStatement.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/MappedStatement.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/MappedStatement.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/MappedStatement.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,133 @@
+package org.apache.ibatis.mapping;
+
+import org.apache.ibatis.cache.Cache;
+import org.apache.ibatis.mapping.Configuration;
+
+import java.util.*;
+
+public class MappedStatement {
+
+ private Configuration configuration;
+ private String id;
+ private Integer fetchSize;
+ private Integer timeout;
+ private StatementType statementType;
+ private ResultSetType resultSetType;
+ private SqlSource sqlSource;
+ private Cache cache;
+ private ParameterMap parameterMap;
+ private List<ResultMap> resultMaps;
+
+ private MappedStatement() {
+ }
+
+ public static class Builder {
+ private MappedStatement mappedStatement = new MappedStatement();
+
+ public Builder(Configuration configuration, String id, SqlSource sqlSource) {
+ mappedStatement.configuration = configuration;
+ mappedStatement.id = id;
+ mappedStatement.sqlSource = sqlSource;
+ mappedStatement.statementType = StatementType.PREPARED;
+ mappedStatement.parameterMap = ParameterMap.EMPTY;
+ mappedStatement.resultMaps = new ArrayList<ResultMap>();
+ mappedStatement.timeout = configuration.getDefaultStatementTimeout();
+ }
+
+ public Builder parameterMap(ParameterMap parameterMap) {
+ mappedStatement.parameterMap = parameterMap;
+ return this;
+ }
+
+ public Builder resultMaps(List<ResultMap> resultMaps) {
+ mappedStatement.resultMaps = resultMaps;
+ return this;
+ }
+
+ public Builder fetchSize(Integer fetchSize) {
+ mappedStatement.fetchSize = fetchSize;
+ return this;
+ }
+
+ public Builder timeout(Integer timeout) {
+ mappedStatement.timeout = timeout;
+ return this;
+ }
+
+ public Builder statementType(StatementType statementType) {
+ mappedStatement.statementType = statementType;
+ return this;
+ }
+
+ public Builder resultSetType(ResultSetType resultSetType) {
+ mappedStatement.resultSetType = resultSetType;
+ return this;
+ }
+
+ public Builder cache(Cache cache) {
+ mappedStatement.cache = cache;
+ return this;
+ }
+
+ public MappedStatement build() {
+ assert mappedStatement.configuration != null;
+ assert mappedStatement.id != null;
+ assert mappedStatement.sqlSource != null;
+ mappedStatement.resultMaps = Collections.unmodifiableList(mappedStatement.resultMaps);
+ return mappedStatement;
+ }
+ }
+
+ public Configuration getConfiguration() {
+ return configuration;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public Integer getFetchSize() {
+ return fetchSize;
+ }
+
+ public Integer getTimeout() {
+ return timeout;
+ }
+
+ public StatementType getStatementType() {
+ return statementType;
+ }
+
+ public ResultSetType getResultSetType() {
+ return resultSetType;
+ }
+
+ public SqlSource getSqlSource() {
+ return sqlSource;
+ }
+
+ public ParameterMap getParameterMap() {
+ return parameterMap;
+ }
+
+ public List<ResultMap> getResultMaps() {
+ return resultMaps;
+ }
+
+ public Cache getCache() {
+ return cache;
+ }
+
+ public String getSql(Object parameterObject) {
+ return sqlSource.getSql(parameterObject);
+ }
+
+ public List<ParameterMapping> getDynamicParameterMappings(Object parameterObject) {
+ List<ParameterMapping> parameterMappings = sqlSource.getParameterMappings(parameterObject);
+ if (parameterMappings == null || parameterMappings.size() <= 0) {
+ parameterMappings = parameterMap.getParameterMappings();
+ }
+ return parameterMappings;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ParameterMap.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ParameterMap.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ParameterMap.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ParameterMap.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,48 @@
+package org.apache.ibatis.mapping;
+
+import java.util.*;
+
+public class ParameterMap {
+
+ public static final ParameterMap EMPTY = new Builder("defaultParameterMap", Object.class, new ArrayList<ParameterMapping>()).build();
+
+ private String id;
+ private Class type;
+ private List<ParameterMapping> parameterMappings;
+
+ private ParameterMap() {
+ }
+
+ public static class Builder {
+ private ParameterMap parameterMap = new ParameterMap();
+
+ public Builder(String id, Class type, List<ParameterMapping> parameterMappings) {
+ parameterMap.id = id;
+ parameterMap.type = type;
+ parameterMap.parameterMappings = parameterMappings;
+ }
+
+ public Class type() {
+ return parameterMap.type;
+ }
+
+ public ParameterMap build() {
+ //lock down collections
+ parameterMap.parameterMappings = Collections.unmodifiableList(parameterMap.parameterMappings);
+ return parameterMap;
+ }
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public Class getType() {
+ return type;
+ }
+
+ public List<ParameterMapping> getParameterMappings() {
+ return parameterMappings;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ParameterMapping.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ParameterMapping.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ParameterMapping.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ParameterMapping.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,91 @@
+package org.apache.ibatis.mapping;
+
+import org.apache.ibatis.type.*;
+
+public class ParameterMapping {
+
+ private String property;
+ private ParameterMode mode;
+ private Class javaType = Object.class;
+ private JdbcType jdbcType;
+ private Integer numericScale;
+ private TypeHandler typeHandler;
+ private String resultMapId;
+
+ private ParameterMapping() {
+ }
+
+ public static class Builder {
+ private ParameterMapping parameterMapping = new ParameterMapping();
+
+ public Builder(String property, TypeHandler typeHandler) {
+ parameterMapping.property = property;
+ parameterMapping.typeHandler = typeHandler;
+ parameterMapping.mode = ParameterMode.IN;
+ }
+
+ public Builder mode(ParameterMode mode) {
+ parameterMapping.mode = mode;
+ return this;
+ }
+
+ public Builder javaType(Class javaType) {
+ parameterMapping.javaType = javaType;
+ return this;
+ }
+
+ public Builder jdbcType(JdbcType jdbcType) {
+ parameterMapping.jdbcType = jdbcType;
+ return this;
+ }
+
+ public Builder numericScale(Integer numericScale) {
+ parameterMapping.numericScale = numericScale;
+ return this;
+ }
+
+ public Builder resultMapId(String resultMapId) {
+ parameterMapping.resultMapId = resultMapId;
+ return this;
+ }
+
+ public Builder typeHandler(TypeHandler typeHandler) {
+ parameterMapping.typeHandler = typeHandler;
+ return this;
+ }
+
+ public ParameterMapping build() {
+ return parameterMapping;
+ }
+
+ }
+
+ public String getProperty() {
+ return property;
+ }
+
+ public ParameterMode getMode() {
+ return mode;
+ }
+
+ public Class getJavaType() {
+ return javaType;
+ }
+
+ public JdbcType getJdbcType() {
+ return jdbcType;
+ }
+
+ public Integer getNumericScale() {
+ return numericScale;
+ }
+
+ public TypeHandler getTypeHandler() {
+ return typeHandler;
+ }
+
+ public String getResultMapId() {
+ return resultMapId;
+ }
+
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ParameterMode.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ParameterMode.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ParameterMode.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ParameterMode.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,5 @@
+package org.apache.ibatis.mapping;
+
+public enum ParameterMode {
+ IN, OUT, INOUT
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultFlag.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultFlag.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultFlag.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultFlag.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,5 @@
+package org.apache.ibatis.mapping;
+
+public enum ResultFlag {
+ ID, CONSTRUCTOR
+}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultMap.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultMap.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultMap.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultMap.java Thu Aug 7 16:21:46 2008
@@ -0,0 +1,91 @@
+package org.apache.ibatis.mapping;
+
+import java.util.*;
+
+public class ResultMap {
+
+ private String id;
+ private Class type;
+ private List<ResultMapping> resultMappings;
+ private List<ResultMapping> idResultMappings;
+ private List<ResultMapping> constructorResultMappings;
+ private List<ResultMapping> propertyResultMappings;
+ private Discriminator discriminator;
+
+ private ResultMap() {
+ }
+
+ public static class Builder {
+ private ResultMap resultMap = new ResultMap();
+
+ public Builder(String id, Class type, List<ResultMapping> resultMappings) {
+ resultMap.id = id;
+ resultMap.type = type;
+ resultMap.resultMappings = resultMappings;
+ }
+
+ public Builder discriminator(Discriminator discriminator) {
+ resultMap.discriminator = discriminator;
+ return this;
+ }
+
+ public Class type() {
+ return resultMap.type;
+ }
+
+ public ResultMap build() {
+ resultMap.idResultMappings = new ArrayList<ResultMapping>();
+ resultMap.constructorResultMappings = new ArrayList<ResultMapping>();
+ resultMap.propertyResultMappings = new ArrayList<ResultMapping>();
+ for (ResultMapping resultMapping : resultMap.resultMappings) {
+ if (resultMapping.getFlags().contains(ResultFlag.CONSTRUCTOR)) {
+ resultMap.constructorResultMappings.add(resultMapping);
+ } else {
+ resultMap.propertyResultMappings.add(resultMapping);
+ }
+ if (resultMapping.getFlags().contains(ResultFlag.ID)) {
+ resultMap.idResultMappings.add(resultMapping);
+ }
+ }
+ if (resultMap.idResultMappings.isEmpty()) {
+ resultMap.idResultMappings.addAll(resultMap.resultMappings);
+ }
+ // lock down collections
+ resultMap.resultMappings = Collections.unmodifiableList(resultMap.resultMappings);
+ resultMap.idResultMappings = Collections.unmodifiableList(resultMap.idResultMappings);
+ resultMap.constructorResultMappings = Collections.unmodifiableList(resultMap.constructorResultMappings);
+ resultMap.propertyResultMappings = Collections.unmodifiableList(resultMap.propertyResultMappings);
+ return resultMap;
+ }
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public Class getType() {
+ return type;
+ }
+
+
+ public List<ResultMapping> getResultMappings() {
+ return resultMappings;
+ }
+
+ public List<ResultMapping> getConstructorResultMappings() {
+ return constructorResultMappings;
+ }
+
+ public List<ResultMapping> getPropertyResultMappings() {
+ return propertyResultMappings;
+ }
+
+ public List<ResultMapping> getIdResultMappings() {
+ return idResultMappings;
+ }
+
+ public Discriminator getDiscriminator() {
+ return discriminator;
+ }
+
+}