A proxy factory.
This namespace delivers all functions needed to (generically) create proxies for JDBC related interfaces and to implement the delegation logic for these proxies that is needed to route method calls through to the real JDBC driver's instances.
In order to hook your own code into the delegation use def-handle
to register your functions for certain method calls.
A proxy factory. This namespace delivers all functions needed to (generically) create proxies for JDBC related interfaces and to implement the delegation logic for these proxies that is needed to route method calls through to the _real_ JDBC driver's instances. In order to hook your own code into the delegation use `def-handle` to register your functions for certain method calls.
(->invoke-event the-method target-obj the-args)
Returns an invoke-event-map.
Returns an _invoke-event-map_.
(->return-event invoke-evt r)
Returns a return-event-map.
Returns a _return-event-map_.
(->throw-event invoke-evt t)
Returns a throw-event-map.
Returns a _throw-event-map_.
(def-handle [clss mthd] [the-method target-obj the-args] body)
Registers a handle
method implementation for dispatch (as of
invocation-key
) value [clss mthd]
. Can be undone via
remove-handle
. Re-registering just overwrites.
Uses fix-prefers!
on the given key. So you may use keys like
(a) [Object :buttle/getCatalog]
and (b)
[java.sql.Connection :buttle/default]
to register an
implementation for (a) specific method names (ignoring the
defining class/interface) and (b) specific interfaces ignoring
the method name (with a preference for (b) in conflicting
cases).
The most specific registration would be [java.sql.Connection :buttle/getCatalog]
. So this would be prefered over (a) and
(b) when present.
Note: This macro (i.e. the resulting code) may not be not
thread-safe because it uses fix-prefers!
which may not be
thread-safe. You should use def-handle
only in top-level-forms for
defining handle
method-implemenations but not in functions you
call as part of the program flow.
Registers a `handle` method implementation for dispatch (as of `invocation-key`) value `[clss mthd]`. Can be undone via `remove-handle`. Re-registering just overwrites. Uses `fix-prefers!` on the given key. So you may use keys like __(a)__ `[Object :buttle/getCatalog]` and __(b)__ `[java.sql.Connection :buttle/default]` to register an implementation for __(a)__ specific method __names__ (ignoring the defining class/interface) and __(b)__ specific interfaces ignoring the method name (with a __preference__ for __(b)__ in conflicting cases). The most specific registration would be `[java.sql.Connection :buttle/getCatalog]`. So this would be prefered over __(a)__ and __(b)__ when present. __Note:__ This macro (i.e. the resulting code) may not be not thread-safe because it uses `fix-prefers!` which may not be thread-safe. You should use `def-handle` only in top-level-forms for defining `handle` method-implemenations but not in functions you call as part of the program flow.
(fix-prefers! [clss mthd])
If (= mthd :buttle/default)
makes all/any method m
of class
clss
(via derive
) a child of :buttle/default
and prefers
[clss :buttle/default]
over [java.lang.Object m]
. This lets you
dispatch via invocation-key
with an inheritance mechanism which
uses/combines isa?
on types (isa? Connection Object)
and on
method keys (isa? :buttle/getCatalog :buttle/default)
.
Now you can (a) def-handle [Object :buttle/getCatalog]
and
(b) def-handle [java.sql.Connection :buttle/default]
with a
preference for (a) when calling Connection/getCatalog
.
This function is thread-safe only if derive
and prefer-method
are so. You will usually not use this function directly but only
through def-handle
.
If `(= mthd :buttle/default)` makes all/any method `m` of class `clss` (via `derive`) a child of `:buttle/default` and _prefers_ `[clss :buttle/default]` over `[java.lang.Object m]`. This lets you dispatch via `invocation-key` with an _inheritance_ mechanism which uses/combines `isa?` on types `(isa? Connection Object)` and on method keys `(isa? :buttle/getCatalog :buttle/default)`. Now you can __(a)__ `def-handle [Object :buttle/getCatalog]` and __(b)__ `def-handle [java.sql.Connection :buttle/default]` with a __preference__ for __(a)__ when calling `Connection/getCatalog`. This function is thread-safe only if `derive` and `prefer-method` are so. You will usually not use this function directly but only through `def-handle`.
Atom carrying a simple/shallow hierarchy of :buttle/<method-name>
to :buttle/default
entries. This hierarchy is used for handle
multi-method and fix-prefers!
.
Atom carrying a simple/shallow hierarchy of `:buttle/<method-name>` to `:buttle/default` entries. This hierarchy is used for `handle` multi-method and `fix-prefers!`.
A generic delegation function (arity [the-method target-obj the-args]
) which delivers proxy'ed return values.
The :default
implementation just delegates to handle-default
.
The multi-method dispatch is done on invocation-key
.
This is a multi-method so that you have a means (see def-handle
)
to hook into the execution/delegation/proxying logic for some/any of
the proxy'ed interface types i.e. invocation-key
dispatch values.
A generic delegation function (arity `[the-method target-obj the-args]`) which delivers proxy'ed return values. The `:default` implementation just delegates to `handle-default`. The multi-method dispatch is done on `invocation-key`. This is a multi-method so that you have a means (see `def-handle`) to hook into the execution/delegation/proxying logic for some/any of the proxy'ed interface types i.e. `invocation-key` dispatch values.
(handle-default the-method target-obj the-args)
Calls the-method
on target-obj
with the-args
, creates a proxy
via make-proxy
(which uses handle
as its handler-fn
) for
non-nil
interface-typed return values and returns the (possibly
proxy'ed) result. Throws if the invoked method throws.
Sends (buttle.event/send-event
) an ->invoke-event
before calling
the-method
. Sends a ->throw-event
if the-method
call
throws. Else sends a ->return-event
before result proxy is
created.
Calls `the-method` on `target-obj` with `the-args`, creates a proxy via `make-proxy` (which uses `handle` as its `handler-fn`) for non-`nil` interface-typed return values and returns the (possibly proxy'ed) result. Throws if the invoked method throws. Sends (`buttle.event/send-event`) an `->invoke-event` before calling `the-method`. Sends a `->throw-event` if `the-method` call throws. Else sends a `->return-event` before result proxy is created.
(invocation-key the-method & _)
Dispatch function for handle
. Returns a vector with the method's
declaring class and buttle/
namespaced keyword for the method's
name.
Example:
(-> java.sql.Connection
(.getMethod "close" nil)
invocation-key)
;; --> [java.sql.Connection :buttle/close]
Dispatch function for `handle`. Returns a vector with the method's declaring class and `buttle/` namespaced keyword for the method's name. Example: (-> java.sql.Connection (.getMethod "close" nil) invocation-key) ;; --> [java.sql.Connection :buttle/close]
(invoke-fn proxy-type target-obj handler-fn the-proxy the-method the-args)
Invocation handler for make-proxy
. It delegates any method
invocation of proxy-type
(which may be an interface or a vector
of interfaces) to handler-fn
. Any other method invocations (like
Object.toString()
) will be invoked on target-object
.
Note that any
java.lang.reflect.InvocationTargetException
(incl. those coming
from handler-fn
) will be un-rolled so that the cause Exception
will come out of invoke-fn
and thus the proxy made by
make-proxy
.
This function is not meant for public usage. It functions as a
hookable delegation-point for make-proxy
so that you may
re-bind/re-def the var when debugging and hacking.
Invocation handler for `make-proxy`. It delegates any method invocation of `proxy-type` (which may be an interface or a vector of interfaces) to `handler-fn`. Any other method invocations (like `Object.toString()`) will be invoked on `target-object`. Note that any `java.lang.reflect.InvocationTargetException` (incl. those coming from `handler-fn`) will be un-rolled so that the cause `Exception` will come out of `invoke-fn` and thus the proxy made by `make-proxy`. This function is not meant for public usage. It functions as a hookable delegation-point for `make-proxy` so that you may re-bind/re-def the var when debugging and hacking.
(make-proxy proxy-type target-obj handler-fn)
A proxy factory.
Creates and returns a Java dynamic proxy with
proxy-type
(which may be an interface or a vector of
interfaces).
The proxy delegates any method invocation to invoke-fn
which in
turn delegates to handler-fn
.
The classloader for this proxy is taken from the first interface. If you want to delegate invocations on this proxy D through handler-fn and onto a Clojure proxy P you have to make sure, that D's and P's method/class declarations are compatible. See notes on classloading in src/buttle/connection_pool_data_source.clj for more details.
Example usage:
(make-proxy java.sql.Driver "foo-driver"
(fn [the-method target-obj the-args]
(condp = (.getName the-method)
"acceptsURL" true
"connect" (proxy [java.sql.Connection] []
(toString [] "foo-connection")))))
A proxy factory. Creates and returns a __Java dynamic proxy__ with `proxy-type` (which may be an interface or a vector of interfaces). The proxy delegates any method invocation to `invoke-fn` which in turn delegates to `handler-fn`. The classloader for this proxy is taken from the first interface. If you want to delegate invocations on this proxy D through handler-fn and onto a Clojure proxy P you have to make sure, that D's and P's method/class declarations are compatible. See notes on classloading in src/buttle/connection_pool_data_source.clj for more details. Example usage: (make-proxy java.sql.Driver "foo-driver" (fn [the-method target-obj the-args] (condp = (.getName the-method) "acceptsURL" true "connect" (proxy [java.sql.Connection] [] (toString [] "foo-connection")))))
(methods-of clss)
Returns seq of :buttle/
namespaced method names of class clss
.
Returns seq of `:buttle/` namespaced method names of class `clss`.
(remove-handle [clss mthd])
Removes the handle
for [clss mthd]
. No-op if there is no
registered handle
for this key.
Removes the `handle` for `[clss mthd]`. No-op if there is no registered `handle` for this key.
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close