Class StatementDecoratorInterceptor

All Implemented Interfaces:
InvocationHandler
Direct Known Subclasses:
StatementCache

public class StatementDecoratorInterceptor extends AbstractCreateStatementInterceptor
Implementation of JdbcInterceptor that proxies statements and result sets so that neither the physical session nor the driver's own handles reach the application through them: Statement.getConnection() is answered with the pool's connection handle rather than the driver's connection, and ResultSet.getStatement() with the statement handle rather than the driver's statement - the hiding of the physical connection this interceptor exists for (Bug 48392, described in this interceptor's section of the jdbc-pool documentation page).

Beyond the hiding, the statement proxy keeps its own handle contract: calls reach the driver statement only while the proxy is open, a repeat close answers as a no-op, every other call on a retired handle is refused with an SQLException, and the driver's answer to a close that failed is passed to the caller - the handle is retired whichever way the driver answered. The connection the proxy reports is a snapshot of the borrow that created it, so a component that reuses a statement across borrows - StatementCache - must re-bind the handle first, as StatementDecoratorInterceptor.StatementProxy.setConnection(Object) documents. The result set proxy answers ResultSet.getStatement() and the Object identity methods (toString, equals, hashCode) itself; every other call, the Wrapper methods included, reaches the driver object unchanged.

  • Field Details

    • RESULTSET_TYPES

      protected static final String[] RESULTSET_TYPES
      Method names that return a ResultSet, spelled with the base class's constants.
    • resultSetConstructor

      protected static volatile Constructor<?> resultSetConstructor
      the constructor to create the resultSet proxies
  • Constructor Details

    • StatementDecoratorInterceptor

      public StatementDecoratorInterceptor()
      Default constructor.
  • Method Details

    • closeInvoked

      public void closeInvoked()
      Description copied from class: AbstractCreateStatementInterceptor
      Method invoked when the operation Connection.close() is invoked. It runs before the close is passed down the chain, so that a hook can still reach the connection while it is alive - statements must be closed before the session is handed to the next borrower. Implementation of this method should be thought through with care, as no actions should trigger an exception. An interceptor that nevertheless throws is isolated: the exception is logged and ignored, the remaining interceptors in the chain still receive the close, and the connection is returned to the pool as it would have been. The fatal virtual machine errors the pool never swallows are the exception: those propagate.
      Specified by:
      closeInvoked in class AbstractCreateStatementInterceptor
    • getResultSetConstructor

      protected Constructor<?> getResultSetConstructor() throws NoSuchMethodException
      Gets the constructor for creating ResultSet proxies.
      Returns:
      the ResultSet proxy constructor
      Throws:
      NoSuchMethodException - if the constructor is not found
    • createStatement

      public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time)
      Wraps the statement the connection call has just created in this interceptor's proxy. This method will be invoked after a successful statement creation. This method can choose to return a wrapper around the statement or return the statement itself. If this method returns a wrapper then it should return a wrapper object that implements one of the following interfaces. Statement, PreparedStatement or CallableStatement

      An implementation must not make the statement reachable from any other code before it returns, because if this method throws then the statement is closed on a best-effort basis by the interceptor base class before the throwable is propagated to the application.

      The time argument is unused - this interceptor does no timing. If building the proxy fails, the failure is logged and the unproxied driver statement is returned, so a failure degrades the connection hiding rather than failing the application's call.

      Specified by:
      createStatement in class AbstractCreateStatementInterceptor
      Parameters:
      proxy - the actual proxy object
      method - the method that was called. It will be one of the methods defined in AbstractCreateStatementInterceptor.STATEMENT_TYPES
      args - the arguments to the method
      statement - the statement that the underlying connection created
      time - elapsed time in milliseconds, measured with the monotonic clock
      Returns:
      a Statement object
    • createDecorator

      protected Object createDecorator(Object proxy, Method method, Object[] args, Object statement, Constructor<?> constructor, String sql) throws InstantiationException, IllegalAccessException, InvocationTargetException
      Creates a proxy for a Statement.
      Parameters:
      proxy - The proxy object on which the method that triggered the creation of the statement was called.
      method - The method that was called on the proxy
      args - The arguments passed as part of the method call to the proxy
      statement - The statement object that is to be proxied
      constructor - The constructor for the desired proxy
      sql - The sql of the statement
      Returns:
      A new proxy for the Statement
      Throws:
      InstantiationException - Couldn't instantiate object
      IllegalAccessException - Inaccessible constructor
      InvocationTargetException - Exception thrown from constructor
    • isResultSet

      protected boolean isResultSet(Method method, boolean process)
      Checks if the given method returns a ResultSet. This, not any executeQuery-specific test, is the dispatch predicate the proxies consult.
      Parameters:
      method - the method to check
      process - whether processing is already enabled
      Returns:
      true if the method returns a ResultSet