Class StatementDecoratorInterceptor.StatementProxy<T extends Statement>

java.lang.Object
org.apache.tomcat.jdbc.pool.interceptor.StatementDecoratorInterceptor.StatementProxy<T>
Type Parameters:
T - The type of Statement being proxied.
All Implemented Interfaces:
InvocationHandler
Direct Known Subclasses:
StatementCache.CachedStatement
Enclosing class:
StatementDecoratorInterceptor

protected class StatementDecoratorInterceptor.StatementProxy<T extends Statement> extends Object implements InvocationHandler
Invocation handler behind a statement proxy: it keeps the handle contract the class javadoc describes - lifecycle answered from its own state, close failures passed on, the borrow's connection handle reported instead of the driver's - and wraps the result sets of the calls named in StatementDecoratorInterceptor.RESULTSET_TYPES.
  • Field Details

    • closed

      protected volatile boolean closed
      Indicates whether this statement has been closed. A statement can be closed from a thread other than the one executing on it - the statement finalizer closes tracked statements from whichever thread closes the connection, and the statement cache forces a close from its own purge - so the flag is written by one thread and read by others, and must be volatile to reach them at all.
    • delegate

      protected volatile T extends Statement delegate
      The delegated statement, nulled once a close has been forwarded. It is read by threads other than the one that nulls it, so, like closed, volatile.
  • Constructor Details

    • StatementProxy

      public StatementProxy(T delegate, String sql)
      Constructs a StatementProxy.
      Parameters:
      delegate - the statement to delegate to
      sql - the SQL text
  • Method Details

    • getDelegate

      public T getDelegate()
      Returns the delegated statement.
      Returns:
      the delegated statement
    • getSql

      public String getSql()
      Returns the SQL text.
      Returns:
      the SQL text
    • setConnection

      public void setConnection(Object proxy)
      Binds the connection handle that getConnection() will report for this statement. createDecorator binds the handle of the borrow that creates the statement, and StatementCache seeds the closing borrow's handle when it parks a statement; the binding is kept as a snapshot and is never refreshed on its own. A handle kept past its borrow is inert by design, so anything reusing a statement proxy across borrows must call this method with the new borrower's handle before the proxy is handed out, as StatementCache does on a cache hit.
      Parameters:
      proxy - the connection proxy
    • getConnection

      public Object getConnection()
      Returns the connection proxy most recently bound through setConnection(Object). While that binding's borrow is current it is a live handle; a statement kept past its borrow answers with the disposed facade it came from. Once the statement is closed the handler refuses the call before it reaches the snapshot, so a stale binding is only visible through diagnostics such as toString().
      Returns:
      the connection proxy
    • setActualProxy

      public void setActualProxy(Object proxy)
      Sets the actual proxy object.
      Parameters:
      proxy - the actual proxy
    • getActualProxy

      public Object getActualProxy()
      Returns the actual proxy object.
      Returns:
      the actual proxy
    • getConstructor

      public Constructor<?> getConstructor()
      Returns the constructor used to create this proxy.
      Returns:
      the constructor
    • setConstructor

      public void setConstructor(Constructor<?> constructor)
      Sets the constructor for creating proxies.
      Parameters:
      constructor - the constructor
    • closeInvoked

      public void closeInvoked() throws SQLException
      Called when the close method is invoked on the statement.

      The driver's answer is passed on to the caller: Statement.close() declares SQLException for a database error while closing, and this proxy reports every other call as the delegate answered it, so a failed close must not come back as a success. The swallowed failure this replaces told the application that the statement was closed while the driver had left its resources on the session the pooled connection was about to hand to the next borrower, and nothing along the path recorded or retried it.

      The handle is retired whichever way the driver answered: the application has been told, and a handle whose close failed must not go on answering calls on a statement the driver may have half released. Where no application waits on the close - the cache dropping a statement, see StatementCache.closeStatement(StatementCache.CachedStatement) - the failure is answered with a log line instead, so that one statement that will not close cannot stop the rest of that purge.

      Throws:
      SQLException - if the underlying statement could not be closed
    • invoke

      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
      Specified by:
      invoke in interface InvocationHandler
      Throws:
      Throwable
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object
    • equals

      public boolean equals(Object obj)
      Overrides:
      equals in class Object
    • toString

      public String toString()
      Overrides:
      toString in class Object