docs: public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          // Special case methods are looked up from a map and invoked.
          // Do not trace because this includes some basic things like hashcode and equals.
          // Important special case methods will take care of tracing themselves.
  
          WSJdbcProxyMethod methImpl = WSJdbcProxyMethod.getSpecialCase(method);
  
          if (methImpl != null)
              return methImpl.invoke(this, proxy, method, args);
  
          // end of special cases
  
          TraceComponent tc = getTracer();
          if (tc.isEntryEnabled())
              Tr.entry(this, tc, toString(proxy, method), args);
  
          // Activation should be handled by the wrapper to which we are delegating.
          Object result = null;
          boolean isOperationComplete = false;
  
          // Invoke on the main wrapper if it has the method.
          DSConfig config = dsConfig.get(); 
          Set<Method> vendorMethods = mcf.vendorMethods; 
  
          if (!vendorMethods.contains(method))
              try 
              {
                  // Locate the equivalent method on the main wrapper and invoke it.
                  Method wrappedMethod = getClass().getMethod(method.getName(), method.getParameterTypes());
                  result = wrappedMethod.invoke(this, args);
                  isOperationComplete = true;
              } catch (NoSuchMethodException methX) {
                  // No FFDC needed. Method doesn't exist on the main wrapper.
                  vendorMethods.add(method); 
              } catch (SecurityException secureX) {
                  // No FFDC needed. Method isn't accessible on the main wrapper.
                  vendorMethods.add(method); 
              } catch (IllegalAccessException accessX) {
                  // No FFDC needed. Method isn't accessible on the main wrapper.
                  vendorMethods.add(method); 
              } catch (InvocationTargetException invokeX) {
                  // Method exists on the main wrapper, and it failed.
                  Throwable x = invokeX.getTargetException();
                  FFDCFilter.processException(x, getClass().getName() + ".invoke", "134", this);
                  x = x instanceof SQLException ? WSJdbcUtil.mapException(this, (SQLException) x) : x;
                  if (tc.isEntryEnabled())
                      Tr.exit(this, tc, toString(proxy, method), x);
                  throw x;
              }
  
          // If the main wrapper does not have the method, invoke it directly on the
          // underlying object.
  
          if (!isOperationComplete) 
          {
              if (tc.isDebugEnabled())
                  Tr.debug(this, tc,
                           "Operation not found on the main wrapper.");
  
              // Filter out unsafe operations.
  
              if (!WSJdbcProxyMethod.isSafe(method) // method name
                  || !WSJdbcProxyMethod.isSafeReturnType(method.getReturnType()) // return type
                  && !WSJdbcProxyMethod.overrideUnsafeReturnType(method)) 
              {
                  // Unsafe method. Not permitted. Raise a SQL exception if possible.
                  // Otherwise, raise a runtime exception.
                  Throwable unsafeX = new SQLFeatureNotSupportedException(
                                  AdapterUtil.getNLSMessage("OPERATION_NOT_PERMITTED", method.getName()));
  
                  Throwable x = null;
                  for (Class<?> xType : method.getExceptionTypes())
                      if (xType.equals(SQLException.class) || xType.equals(SQLFeatureNotSupportedException.class)) {
                          x = unsafeX;
                          break;
                      }
  
                  if (x == null)
                      x = new RuntimeException(unsafeX);
  
                  if (tc.isEntryEnabled())
                      Tr.exit(this, tc, toString(proxy, method), unsafeX);
                  throw x;
              }
  
              // Invoke the operation directly on the underlying implementation.
  
              activate(); 
  
              Object implObject = dynamicWrapperToImpl.get(proxy);
  
              // A missing entry in the dynamic-wrapper-to-impl map indicates the wrapper is
              // either,
              // 1) Closed because the parent wrapper is closed.
              // 2) No longer valid due to handle association with a managed connection that
              //    doesn't implement the same vendor interface.
  
              if (implObject == null) {
                  String message = AdapterUtil.getNLSMessage("OBJECT_CLOSED", "Wrapper");
                  Throwable closedX = new SQLRecoverableException(message, "08003", 0);
  
                  // Raise the SQLException if we can.
  
                  boolean raisesSQLX = false;
  
                  for (Class<?> xClass : method.getExceptionTypes())
                      raisesSQLX |= xClass.equals(SQLException.class);
  
                  // Otherwise use RuntimeException.
  
                  if (!raisesSQLX)
                      closedX = new RuntimeException(closedX);
  
                  if (tc.isEntryEnabled())
                      Tr.exit(this, tc, toString(proxy, method), closedX);
                  throw closedX;
              }
  
              WSJdbcConnection connWrapper = null; 
              // If configured to do so, attempt to enlist in a transaction or start a new one.
              if (this instanceof WSJdbcObject) {
                  connWrapper = (WSJdbcConnection) ((WSJdbcObject) this).getConnectionWrapper(); 
  
                  if (connWrapper != null
                      && (dsConfig.get().beginTranForVendorAPIs || WSJdbcProxyMethod.alwaysBeginTranMethods.contains(method.getName())))
                      connWrapper.beginTransactionIfNecessary();
              }
  
              try {
                  // Allow the data source to override in order to account for
                  // dynamic configuration changes. 
  
                  result = invokeOperation(implObject, method, args); 
  
                  // If a client information setting was changed, update the managed connection
                  // so that we know to reset the client information before pooling the connection.
                  if (connWrapper != null && WSJdbcProxyMethod.isClientInfoSetter(method.getName()))
                      connWrapper.managedConn.clientInfoExplicitlySet = true;
              } catch (InvocationTargetException invokeX) {
                  Throwable x = invokeX.getTargetException();
                  FFDCFilter.processException(x, getClass().getName() + ".invoke", "171", this);
                  x = x instanceof SQLException ? WSJdbcUtil.mapException(this, (SQLException) x) : x;
                  if (tc.isEntryEnabled())
                      Tr.exit(this, tc, toString(proxy, method), x);
                  throw x;
              }
          } // reflection error from invocation attempt on main wrapper
  
          if (tc.isEntryEnabled())
              Tr.exit(this, tc, toString(proxy, method), result); 
          return result;
      }