Class JdbcInterceptor

java.lang.Object
org.apache.tomcat.jdbc.pool.JdbcInterceptor
All Implemented Interfaces:
InvocationHandler
Direct Known Subclasses:
AbstractCreateStatementInterceptor, ConnectionState, DisposableConnectionFacade, ProxyConnection, TrapException

public abstract class JdbcInterceptor extends Object implements InvocationHandler
Abstract class that is to be extended for implementations of interceptors. When an operation is called on the Connection handle the pool hands out, the call travels down the interceptor chain; an interceptor that does not answer a call itself continues it by returning super.invoke(proxy, method, args). A few calls are answered before the chain is entered - the DisposableConnectionFacade on top of every handle answers Object.equals(Object) and Object.hashCode() itself, and a handle whose borrow has ended is refused by that facade - but everything else reaches each link of the chain. Interceptors are useful to change or improve behavior of the connection pool.
Interceptors can receive a set of properties. Each sub class is responsible for parsing the properties during runtime when they are needed or simply override the setProperties(Map) method. Properties arrive in a key-value pair of Strings as they were received through the configuration. One set of interceptor instances is built per pooled connection (see setProperties(Map)), plus a throwaway instance per configured class for each of the poolStarted(ConnectionPool) and poolClosed(ConnectionPool) notifications. Hooks and invoke(Object, Method, Object[]) can arrive from any thread that touches the pool: borrower threads run the chain, while pool management threads run reset(ConnectionPool, PooledConnection) and disconnected(ConnectionPool, PooledConnection, boolean) when a connection is shut down.
  • Field Details

  • Constructor Details

    • JdbcInterceptor

      public JdbcInterceptor()
      Public constructor for instantiation through reflection
  • Method Details

    • invoke

      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
      Gets invoked each time an operation on Connection is invoked.

      The base implementation passes the call to the next interceptor in the chain. When there is no next interceptor, the call fails fast with a NullPointerException: a chain built by the pool always ends in the ProxyConnection terminal, so reaching this case means a chain was hand-built without a terminal link. Interceptors that do not answer a call themselves continue it with super.invoke(proxy, method, args).

      Specified by:
      invoke in interface InvocationHandler
      Throws:
      Throwable
    • getNext

      public JdbcInterceptor getNext()
      Returns the next interceptor in the chain
      Returns:
      the next interceptor in the chain
    • setNext

      public void setNext(JdbcInterceptor next)
      configures the next interceptor in the chain
      Parameters:
      next - The next chain item
    • unregisterMBean

      public void unregisterMBean()
      Releases any MBean this interceptor published for the connection it serves, without tearing down the connection state. The pool calls this when it releases its own MBean while the pool stays live; the connection and its chain remain usable, and a later borrow can publish the interceptor again. The default does nothing; an interceptor that publishes an MBean overrides it.
    • compare

      public boolean compare(String name1, String name2)
      Performs a string comparison, using references unless the useEquals property is set to true.
      Parameters:
      name1 - The first name
      name2 - The second name
      Returns:
      true if name1 is equal to name2 based on useEquals
    • compare

      public boolean compare(String methodName, Method method)
      Compares a method name (String) to a method (Method) compare(String,String) Uses reference comparison unless the useEquals property is set to true
      Parameters:
      methodName - The method name
      method - The method
      Returns:
      true if the name matches
    • reset

      public abstract void reset(ConnectionPool parent, PooledConnection con)
      Gets called each time the connection is borrowed from the pool This means that if an interceptor holds a reference to the connection the interceptor can be reused for another connection.
      This method may be called with null as both arguments when we are closing down the connection. When called for a shutdown reset, an interceptor that throws is isolated: the exception is logged and ignored, and the remaining interceptors in the chain are reset as well.
      Chain topology is owned by the pool: a hook must not call setNext(JdbcInterceptor) on itself or on any other link while the chain is wired, and in particular not from this callback. The walks that run this callback do not agree on when they read the next link - the walk at borrow time re-reads it after the callback, the shutdown walks read it before - so a hook that rewired its own link would be visited differently depending on which walk runs, and could be skipped or revisited without limit.
      Parameters:
      parent - - the connection pool owning the connection
      con - - the pooled connection
    • disconnected

      public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing)
      Called when Connection.close() is called on the underlying connection. This is to notify the interceptors, that the physical connection has been released. 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 are still notified, and the physical connection is closed as it would have been. As for reset(ConnectionPool, PooledConnection), a hook must not rewire the chain from this callback: chain topology is owned by the pool.
      Parameters:
      parent - - the connection pool that this connection belongs to
      con - - the pooled connection that holds this connection
      finalizing - - if this connection is finalizing. True means that the pooled connection will not reconnect the underlying connection
    • getProperties

      public Map<String, PoolProperties.InterceptorProperty> getProperties()
      Returns the properties configured for this interceptor. The map is shared with every other interceptor instance created from the same interceptor definition and with every later chain build, so it must be treated as read-only: mutating it changes what all those instances and all later chains see.
      Returns:
      the configured properties for this interceptor, to be treated as read-only
    • setProperties

      public void setProperties(Map<String, PoolProperties.InterceptorProperty> properties)
      Called during the creation of an interceptor, once per instance: once for each instance created to build a pooled connection's interceptor chain, and once on the throwaway instance of each configured class that receives poolStarted(ConnectionPool) at pool start and poolClosed(ConnectionPool) at pool close. The pool passes the live map of the interceptor definition, shared across all these instances, so it must be treated as read-only (see getProperties()). Override this method to perform type casts between string values and object properties.
      Parameters:
      properties - The properties
    • isUseEquals

      public boolean isUseEquals()
      True if the compare method uses the Object.equals(Object) method, false if comparison is done on a reference level.
      Returns:
      true if equals is used for comparisons
    • setUseEquals

      public void setUseEquals(boolean useEquals)
      Set to true if string comparisons (for the compare(String, Method) and compare(String, String) methods) should use the Object.equals(Object) method The default is true
      Parameters:
      useEquals - true if equals will be used for comparisons
    • poolClosed

      public void poolClosed(ConnectionPool pool)
      This method is invoked by a connection pool when the pool is closed. Interceptor classes can override this method if they keep static variables or other tracking means around. This method is only invoked on a single instance of the interceptor, and not on every instance created. That instance is a throwaway created solely for this notification: it shares no state with the instances in any connection's chain, so any state this hook needs must be static or keyed on the pool. The callback is delivered for every definition the pool told about its start, whatever the interceptor configuration lists by the time the pool closes, and additionally for any definition the configuration has gained since the start. An override that registers state at the start must therefore find its release delivered even after its definition has been removed from a live pool's configuration, and must tolerate a delivery it did not pair with its own start. An exception thrown here is logged at debug level and otherwise ignored; the pool close continues.
      Parameters:
      pool - - the pool that is being closed.
    • poolStarted

      public void poolStarted(ConnectionPool pool)
      This method is invoked by a connection pool when the pool is first started up, usually when the first connection is requested. Interceptor classes can override this method if they keep static variables or other tracking means around. This method is only invoked on a single instance of the interceptor, and not on every instance created. That instance is a throwaway created solely for this notification: it shares no state with the instances in any connection's chain or with the instance that later receives poolClosed(ConnectionPool), so any state this hook needs must be static or keyed on the pool. An exception thrown here aborts pool initialization: the pool is closed and the failure is reported to the caller that triggered the start-up.
      Parameters:
      pool - - the pool that is being started up.