Added:
branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/JDBC4PreparedStatementWrapper.java
branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/JDBC4StatementWrapper.java
Modified:
branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/JDBC4ConnectionWrapper.java
branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/StatementWrapper.java
branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/WrapperBase.java
Log:
Support for unwrapping on statements, prepared statements.
Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/JDBC4ConnectionWrapper.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/JDBC4ConnectionWrapper.java 2007-04-20 21:43:11 UTC (rev 6405)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/JDBC4ConnectionWrapper.java 2007-04-22 02:14:34 UTC (rev 6406)
@@ -291,8 +291,6 @@
}
}
- private Map unwrappedInterfaces = null;
-
/**
* @see java.sql.Connection#createBlob()
*/
@@ -337,66 +335,4 @@
return null; // never reached, but compiler can't tell
}
-
- private static final SQLException SQL_EXCEPTION_INSTANCE = new SQLException();
-
- class ConnectionErrorFiringInvocationHandler implements InvocationHandler {
- Object invokeOn = null;
-
- public ConnectionErrorFiringInvocationHandler(Object toInvokeOn) {
- invokeOn = toInvokeOn;
- }
-
- public Object invoke(Object proxy, Method method,
- Object[] args) throws Throwable {
- Object result = null;
-
- try {
- result = method.invoke(invokeOn, args);
-
- if (result != null) {
- Class[] interfaces = result.getClass().getInterfaces();
-
- if (interfaces.length > 0) {
-
- // TODO: Cache this
- Method[] resultMethods = result.getClass().getMethods();
-
- for (int i = 0; i < resultMethods.length; i++) {
- Class[] exceptionTypes = resultMethods[i].getExceptionTypes();
-
- boolean needsWrapped = false;
-
- for (int j = 0; j < exceptionTypes.length; j++) {
- if (exceptionTypes[j].isInstance(SQL_EXCEPTION_INSTANCE)) {
- // Needs to be wrapped too - to catch SQLExceptions
- // and fire events if needed
-
- needsWrapped = true;
-
- break;
- }
- }
-
- if (needsWrapped) {
- result = Proxy.newProxyInstance(result.getClass()
- .getClassLoader(), interfaces,
- new ConnectionErrorFiringInvocationHandler(result));
- break;
- }
- }
- }
- }
- } catch (InvocationTargetException e) {
- if (e.getTargetException() instanceof SQLException) {
- checkAndFireConnectionError((SQLException) e
- .getTargetException());
- } else {
- throw e;
- }
- }
-
- return result;
- }
- }
}
Added: branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/JDBC4PreparedStatementWrapper.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/JDBC4PreparedStatementWrapper.java 2007-04-20 21:43:11 UTC (rev 6405)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/JDBC4PreparedStatementWrapper.java 2007-04-22 02:14:34 UTC (rev 6406)
@@ -0,0 +1,513 @@
+/*
+ Copyright (C) 2002-2007 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ There are special exceptions to the terms and conditions of the GPL
+ as it is applied to this software. View the full text of the
+ exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
+ software distribution.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+ */
+package com.mysql.jdbc.jdbc2.optional;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.RowId;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLXML;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import com.mysql.jdbc.ConnectionImpl;
+import com.mysql.jdbc.SQLError;
+import com.mysql.jdbc.jdbc2.optional.ConnectionWrapper;
+import com.mysql.jdbc.jdbc2.optional.MysqlPooledConnection;
+
+/**
+ */
+public class JDBC4PreparedStatementWrapper extends PreparedStatementWrapper {
+
+ JDBC4PreparedStatementWrapper(ConnectionWrapper c, MysqlPooledConnection conn,
+ PreparedStatement toWrap) {
+ super(c, conn, toWrap);
+ }
+
+ public void close() throws SQLException {
+ try {
+ super.close();
+ } finally {
+ this.unwrappedInterfaces = null;
+ }
+ }
+
+ public boolean isClosed() throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ return this.wrappedStmt.isClosed();
+ } else {
+ throw SQLError.createSQLException("Statement already closed",
+ SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+
+ return false; // never get here - compiler can't tell
+ }
+
+ public void setPoolable(boolean poolable) throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ this.wrappedStmt.setPoolable(poolable);
+ } else {
+ throw SQLError.createSQLException("Statement already closed",
+ SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public boolean isPoolable() throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ return this.wrappedStmt.isPoolable();
+ } else {
+ throw SQLError.createSQLException("Statement already closed",
+ SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+
+ return false; // never get here - compiler can't tell
+ }
+
+ public void setRowId(int parameterIndex, RowId x) throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setRowId(parameterIndex,
+ x);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setNClob(int parameterIndex, NClob value) throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex,
+ value);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setSQLXML(int parameterIndex, SQLXML xmlObject)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setSQLXML(parameterIndex,
+ xmlObject);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+
+ public void setNString(int parameterIndex,
+ String value)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setNString(parameterIndex,
+ value);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setNCharacterStream(int parameterIndex,
+ Reader value,
+ long length)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setNCharacterStream(parameterIndex,
+ value, length);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setClob(int parameterIndex,
+ Reader reader,
+ long length)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setClob(parameterIndex,
+ reader, length);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setBlob(int parameterIndex,
+ InputStream inputStream,
+ long length)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setBlob(parameterIndex,
+ inputStream, length);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setNClob(int parameterIndex,
+ Reader reader,
+ long length)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex,
+ reader, length);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setAsciiStream(int parameterIndex,
+ InputStream x,
+ long length)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setAsciiStream(parameterIndex,
+ x, length);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setBinaryStream(int parameterIndex,
+ InputStream x,
+ long length)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setBinaryStream(parameterIndex,
+ x, length);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setCharacterStream(int parameterIndex,
+ Reader reader,
+ long length)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setCharacterStream(parameterIndex,
+ reader, length);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setAsciiStream(int parameterIndex,
+ InputStream x)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setAsciiStream(parameterIndex,
+ x);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setBinaryStream(int parameterIndex,
+ InputStream x)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setBinaryStream(parameterIndex,
+ x);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setCharacterStream(int parameterIndex,
+ Reader reader)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setCharacterStream(parameterIndex,
+ reader);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+
+ }
+
+ public void setNCharacterStream(int parameterIndex,
+ Reader value)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setNCharacterStream(parameterIndex,
+ value);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+
+ }
+
+ public void setClob(int parameterIndex,
+ Reader reader)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setClob(parameterIndex,
+ reader);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+
+ }
+
+ public void setBlob(int parameterIndex,
+ InputStream inputStream)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setBlob(parameterIndex,
+ inputStream);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setNClob(int parameterIndex,
+ Reader reader)
+ throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ ((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex,
+ reader);
+ } else {
+ throw SQLError.createSQLException(
+ "No operations allowed after statement closed",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ /**
+ * Returns true if this either implements the interface argument or is
+ * directly or indirectly a wrapper for an object that does. Returns false
+ * otherwise. If this implements the interface then return true, else if
+ * this is a wrapper then return the result of recursively calling
+ * <code>isWrapperFor</code> on the wrapped object. If this does not
+ * implement the interface and is not a wrapper, return false. This method
+ * should be implemented as a low-cost operation compared to
+ * <code>unwrap</code> so that callers can use this method to avoid
+ * expensive <code>unwrap</code> calls that may fail. If this method
+ * returns true then calling <code>unwrap</code> with the same argument
+ * should succeed.
+ *
+ * @param interfaces
+ * a Class defining an interface.
+ * @return true if this implements the interface or directly or indirectly
+ * wraps an object that does.
+ * @throws java.sql.SQLException
+ * if an error occurs while determining whether this is a
+ * wrapper for an object with the given interface.
+ * @since 1.6
+ */
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+
+ boolean isInstance = iface.isInstance(this);
+
+ if (isInstance) {
+ return true;
+ }
+
+ return (iface.isInstance(com.mysql.jdbc.Statement.class)
+ || iface.isInstance(java.sql.Statement.class)
+ || iface.isInstance(java.sql.PreparedStatement.class)
+ || iface.isInstance(java.sql.Wrapper.class));
+ }
+
+ /**
+ * Returns an object that implements the given interface to allow access to
+ * non-standard methods, or standard methods not exposed by the proxy. The
+ * result may be either the object found to implement the interface or a
+ * proxy for that object. If the receiver implements the interface then that
+ * is the object. If the receiver is a wrapper and the wrapped object
+ * implements the interface then that is the object. Otherwise the object is
+ * the result of calling <code>unwrap</code> recursively on the wrapped
+ * object. If the receiver is not a wrapper and does not implement the
+ * interface, then an <code>SQLException</code> is thrown.
+ *
+ * @param iface
+ * A Class defining an interface that the result must implement.
+ * @return an object that implements the interface. May be a proxy for the
+ * actual implementing object.
+ * @throws java.sql.SQLException
+ * If no object found that implements the interface
+ * @since 1.6
+ */
+ public synchronized <T> T unwrap(java.lang.Class<T> iface)
+ throws java.sql.SQLException {
+ try {
+ if ("java.sql.Statement".equals(iface.getName())
+ || "java.sql.PreparedStatement".equals(iface.getName())
+ || "java.sql.Wrapper.class".equals(iface.getName())) {
+ return iface.cast(this);
+ }
+
+ if (unwrappedInterfaces == null) {
+ unwrappedInterfaces = new HashMap();
+ }
+
+ Object cachedUnwrapped = unwrappedInterfaces.get(iface);
+
+ if (cachedUnwrapped == null) {
+ if (cachedUnwrapped == null) {
+ cachedUnwrapped = Proxy.newProxyInstance(
+ this.wrappedStmt.getClass().getClassLoader(),
+ new Class[] { iface },
+ new ConnectionErrorFiringInvocationHandler(this.wrappedStmt));
+ unwrappedInterfaces.put(iface, cachedUnwrapped);
+ }
+ unwrappedInterfaces.put(iface, cachedUnwrapped);
+ }
+
+ return iface.cast(cachedUnwrapped);
+ } catch (ClassCastException cce) {
+ throw SQLError.createSQLException("Unable to unwrap to "
+ + iface.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+ }
+ }
+}
Added: branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/JDBC4StatementWrapper.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/JDBC4StatementWrapper.java 2007-04-20 21:43:11 UTC (rev 6405)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/JDBC4StatementWrapper.java 2007-04-22 02:14:34 UTC (rev 6406)
@@ -0,0 +1,192 @@
+/*
+ Copyright (C) 2002-2007 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ There are special exceptions to the terms and conditions of the GPL
+ as it is applied to this software. View the full text of the
+ exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
+ software distribution.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+ */
+package com.mysql.jdbc.jdbc2.optional;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.NClob;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import com.mysql.jdbc.ConnectionImpl;
+import com.mysql.jdbc.SQLError;
+import com.mysql.jdbc.jdbc2.optional.ConnectionWrapper;
+import com.mysql.jdbc.jdbc2.optional.MysqlPooledConnection;
+
+/**
+ */
+public class JDBC4StatementWrapper extends StatementWrapper {
+
+ protected JDBC4StatementWrapper(ConnectionWrapper c,
+ MysqlPooledConnection conn,
+ Statement toWrap) {
+ super(c, conn, toWrap);
+ }
+
+ public void close() throws SQLException {
+ try {
+ super.close();
+ } finally {
+ this.unwrappedInterfaces = null;
+ }
+ }
+
+ public boolean isClosed() throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ return this.wrappedStmt.isClosed();
+ } else {
+ throw SQLError.createSQLException("Statement already closed",
+ SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public void setPoolable(boolean poolable) throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ this.wrappedStmt.setPoolable(poolable);
+ } else {
+ throw SQLError.createSQLException("Statement already closed",
+ SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ public boolean isPoolable() throws SQLException {
+ try {
+ if (this.wrappedStmt != null) {
+ return this.wrappedStmt.isPoolable();
+ } else {
+ throw SQLError.createSQLException("Statement already closed",
+ SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+ }
+ } catch (SQLException sqlEx) {
+ checkAndFireConnectionError(sqlEx);
+ }
+ }
+
+ /**
+ * Returns true if this either implements the interface argument or is
+ * directly or indirectly a wrapper for an object that does. Returns false
+ * otherwise. If this implements the interface then return true, else if
+ * this is a wrapper then return the result of recursively calling
+ * <code>isWrapperFor</code> on the wrapped object. If this does not
+ * implement the interface and is not a wrapper, return false. This method
+ * should be implemented as a low-cost operation compared to
+ * <code>unwrap</code> so that callers can use this method to avoid
+ * expensive <code>unwrap</code> calls that may fail. If this method
+ * returns true then calling <code>unwrap</code> with the same argument
+ * should succeed.
+ *
+ * @param interfaces
+ * a Class defining an interface.
+ * @return true if this implements the interface or directly or indirectly
+ * wraps an object that does.
+ * @throws java.sql.SQLException
+ * if an error occurs while determining whether this is a
+ * wrapper for an object with the given interface.
+ * @since 1.6
+ */
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+
+ boolean isInstance = iface.isInstance(this);
+
+ if (isInstance) {
+ return true;
+ }
+
+ return (iface.isInstance(com.mysql.jdbc.Statement.class)
+ || iface.isInstance(java.sql.Statement.class)
+ || iface.isInstance(java.sql.Wrapper.class));
+ }
+
+ /**
+ * Returns an object that implements the given interface to allow access to
+ * non-standard methods, or standard methods not exposed by the proxy. The
+ * result may be either the object found to implement the interface or a
+ * proxy for that object. If the receiver implements the interface then that
+ * is the object. If the receiver is a wrapper and the wrapped object
+ * implements the interface then that is the object. Otherwise the object is
+ * the result of calling <code>unwrap</code> recursively on the wrapped
+ * object. If the receiver is not a wrapper and does not implement the
+ * interface, then an <code>SQLException</code> is thrown.
+ *
+ * @param iface
+ * A Class defining an interface that the result must implement.
+ * @return an object that implements the interface. May be a proxy for the
+ * actual implementing object.
+ * @throws java.sql.SQLException
+ * If no object found that implements the interface
+ * @since 1.6
+ */
+ public synchronized <T> T unwrap(java.lang.Class<T> iface)
+ throws java.sql.SQLException {
+ try {
+ if ("java.sql.Statement".equals(iface.getName())
+ || "java.sql.Wrapper.class".equals(iface.getName())) {
+ return iface.cast(this);
+ }
+
+ if (unwrappedInterfaces == null) {
+ unwrappedInterfaces = new HashMap();
+ }
+
+ Object cachedUnwrapped = unwrappedInterfaces.get(iface);
+
+ if (cachedUnwrapped == null) {
+ cachedUnwrapped = Proxy.newProxyInstance(
+ this.wrappedStmt.getClass().getClassLoader(),
+ new Class[] { iface },
+ new ConnectionErrorFiringInvocationHandler(this.wrappedStmt));
+ unwrappedInterfaces.put(iface, cachedUnwrapped);
+ }
+
+ return iface.cast(cachedUnwrapped);
+ } catch (ClassCastException cce) {
+ throw SQLError.createSQLException("Unable to unwrap to "
+ + iface.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+ }
+ }
+}
Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/StatementWrapper.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/StatementWrapper.java 2007-04-20 21:43:11 UTC (rev 6405)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/StatementWrapper.java 2007-04-22 02:14:34 UTC (rev 6406)
@@ -25,7 +25,6 @@
package com.mysql.jdbc.jdbc2.optional;
import com.mysql.jdbc.SQLError;
-import com.mysql.jdbc.exceptions.NotYetImplementedException;
import java.sql.Connection;
import java.sql.ResultSet;
@@ -827,55 +826,4 @@
checkAndFireConnectionError(sqlEx);
}
}
-//
-// public boolean isClosed() throws SQLException {
-// try {
-// if (this.wrappedStmt != null) {
-// return this.wrappedStmt.isClosed();
-// } else {
-// throw SQLError.createSQLException("Statement already closed",
-// SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-// }
-// } catch (SQLException sqlEx) {
-// checkAndFireConnectionError(sqlEx);
-// }
-//
-// return true;
-// }
-//
-// public boolean isPoolable() throws SQLException {
-// try {
-// if (this.wrappedStmt != null) {
-// return this.wrappedStmt.isPoolable();
-// } else {
-// throw SQLError.createSQLException("Statement already closed",
-// SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-// }
-// } catch (SQLException sqlEx) {
-// checkAndFireConnectionError(sqlEx);
-// }
-//
-// return true;
-// }
-//
-// public void setPoolable(boolean poolable) throws SQLException {
-// try {
-// if (this.wrappedStmt != null) {
-// this.wrappedStmt.setPoolable(poolable);
-// } else {
-// throw SQLError.createSQLException("Statement already closed",
-// SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-// }
-// } catch (SQLException sqlEx) {
-// checkAndFireConnectionError(sqlEx);
-// }
-// }
-//
-// public boolean isWrapperFor(Class arg0) throws SQLException {
-// throw new NotYetImplementedException();
-// }
-//
-// public Object unwrap(Class arg0) throws SQLException {
-// throw new NotYetImplementedException();
-// }
}
Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/WrapperBase.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/WrapperBase.java 2007-04-20 21:43:11 UTC (rev 6405)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/WrapperBase.java 2007-04-22 02:14:34 UTC (rev 6406)
@@ -24,7 +24,12 @@
*/
package com.mysql.jdbc.jdbc2.optional;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.sql.SQLException;
+import java.util.Map;
import com.mysql.jdbc.SQLError;
@@ -58,4 +63,50 @@
throw sqlEx;
}
+
+ protected Map unwrappedInterfaces = null;
+
+ protected class ConnectionErrorFiringInvocationHandler implements InvocationHandler {
+ Object invokeOn = null;
+
+ public ConnectionErrorFiringInvocationHandler(Object toInvokeOn) {
+ invokeOn = toInvokeOn;
+ }
+
+ public Object invoke(Object proxy, Method method,
+ Object[] args) throws Throwable {
+ Object result = null;
+
+ try {
+ result = method.invoke(invokeOn, args);
+
+ if (result != null) {
+ Class[] interfaces = result.getClass().getInterfaces();
+
+ for (int i = 0; i < interfaces.length; i++) {
+ String packageName = interfaces[i].getPackage().getName();
+
+ if ("java.sql".equals(packageName) ||
+ "javax.sql".equals(packageName)) {
+ // needs wrapped
+
+ result = Proxy.newProxyInstance(result.getClass()
+ .getClassLoader(), interfaces,
+ new ConnectionErrorFiringInvocationHandler(result));
+ break;
+ }
+ }
+ }
+ } catch (InvocationTargetException e) {
+ if (e.getTargetException() instanceof SQLException) {
+ checkAndFireConnectionError((SQLException) e
+ .getTargetException());
+ } else {
+ throw e;
+ }
+ }
+
+ return result;
+ }
+ }
}
\ No newline at end of file
| Thread |
|---|
| • Connector/J commit: r6406 - branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional | mmatthews | 22 Apr |