Writing reflexive extension functions in Java

Reflexive extension functions written in Java map the namespace of the XPath function name to a Java fully-qualified class name, and the local name of the function to a Java method or field name.

Java extension functions can also be used when you are running on the .NET platform, provided the class implementing the function is a standard class in the OpenJDK class library (which covers nearly all the classes defined in the JDK). In other cases, you should compile the Java code into a .NET assembly using the IKVMC compiler, in which case it behaves in the same way as an extension function written in any other .NET language and compiled into CIL: see Writing extension functions under .NET

An extension function is invoked using a name such as prefix:localname(). The prefix must be the prefix associated with a namespace declaration that is in scope. The namespace URI is used to identify a Java class, and the local name is used to identify a method, field, or constructor within the class.

There are a number of extension functions supplied with the Saxon product: for details, see Extensions. The source code of these methods, which in most cases is extremely simple, can be used as an example for writing other user extension functions. It is found in class net.sf.saxon.functions.Extensions.

The command line option -TJ is useful for debugging the loading of Java extensions. It gives detailed information about the methods that are examined for a possible match.

Identifying the Java Class

There are various ways a mapping from URIs to Java classes can be established. The simplest is to use a URI that identifies the Java class explicitly. The namespace URI should be "java:" followed by the fully-qualified class name (for example xmlns:date="java:java.util.Date"). The class must be on the classpath.

For compatibility with other products and previous Saxon releases, Saxon at user request also supports certain other formats of URI. The URI may be a string containing a "/", in which the fully-qualified class name appears after the final "/". (for example xmlns:date=""). The part of the URI before the final "/" is immaterial. The format xmlns:date="java.util.Date" is also supported. To permit this extended syntax for namespaces, you need to call the method setStrictJavaUriFormat(false) on the JavaExtensionLibrary object, which can be obtained from the Configuration.

The Saxon namespace URI is recognised as a special case. In most cases it causes the function to be loaded from the class net.sf.saxon.functions.Extensions but in a few cases, such as saxon:evaluate, the function is recognized by the compiler as if it were a built-in function. The various EXSLT namespaces are also recognized specially.

In XSLT, the system function function-available(String name) returns true if there appears to be a method available with the right name. The function also has an optional second argument to test whether there is a method with the appropriate number of arguments. However, it is not possible to test whether the arguments are of appropriate types. If the function name is "new" it returns true so long as the class is not an abstract class or interface, and so long as it has at least one constructor.

Identifying the Java constructor, method, or field

The local name used in the XPath function call determines which constructor, method, or field of the Java class is invoked. This decision (called binding) is always made at the time the XPath expression is compiled. (In previous Saxon releases it was sometimes delayed until the actual argument values were known at run-time).