View source with raw comments or as raw
    1/*  Part of JPL -- SWI-Prolog/Java interface
    2
    3    Author:        Paul Singleton, Fred Dushin and Jan Wielemaker
    4    E-mail:        paul@jbgb.com
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  2004-2017, Paul Singleton
    7    All rights reserved.
    8
    9    Redistribution and use in source and binary forms, with or without
   10    modification, are permitted provided that the following conditions
   11    are met:
   12
   13    1. Redistributions of source code must retain the above copyright
   14       notice, this list of conditions and the following disclaimer.
   15
   16    2. Redistributions in binary form must reproduce the above copyright
   17       notice, this list of conditions and the following disclaimer in
   18       the documentation and/or other materials provided with the
   19       distribution.
   20
   21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   25    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   29    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   31    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32    POSSIBILITY OF SUCH DAMAGE.
   33*/
   34
   35:- module(jpl,
   36    [   jpl_get_default_jvm_opts/1,
   37        jpl_set_default_jvm_opts/1,
   38        jpl_get_actual_jvm_opts/1,
   39        jpl_pl_lib_version/1,
   40        jpl_c_lib_version/1,
   41        jpl_pl_syntax/1,
   42        jpl_new/3,
   43        jpl_call/4,
   44        jpl_get/3,
   45        jpl_set/3,
   46        jpl_servlet_byref/3,
   47        jpl_servlet_byval/3,
   48        jpl_class_to_classname/2,
   49        jpl_class_to_type/2,
   50        jpl_classname_to_class/2,
   51        jpl_classname_to_type/2,
   52        jpl_datum_to_type/2,
   53        jpl_false/1,
   54        jpl_is_class/1,
   55        jpl_is_false/1,
   56        jpl_is_null/1,
   57        jpl_is_object/1,
   58        jpl_is_object_type/1,
   59        jpl_is_ref/1,
   60        jpl_is_true/1,
   61        jpl_is_type/1,
   62        jpl_is_void/1,
   63        jpl_null/1,
   64        jpl_object_to_class/2,
   65        jpl_object_to_type/2,
   66        jpl_primitive_type/1,
   67        jpl_ref_to_type/2,
   68        jpl_true/1,
   69        jpl_type_to_class/2,
   70        jpl_type_to_classname/2,
   71        jpl_void/1,
   72        jpl_array_to_length/2,
   73        jpl_array_to_list/2,
   74        jpl_datums_to_array/2,
   75        jpl_enumeration_element/2,
   76        jpl_enumeration_to_list/2,
   77        jpl_hashtable_pair/2,
   78        jpl_iterator_element/2,
   79        jpl_list_to_array/2,
   80        jpl_terms_to_array/2,
   81        jpl_array_to_terms/2,
   82        jpl_map_element/2,
   83        jpl_set_element/2
   84    ]).   85:- use_module(library(lists)).   86:- use_module(library(apply)).   87:- use_module(library(debug)).

A Java interface for SWI Prolog 7.x

The library(jpl) provides a bidirectional interface to a Java Virtual Machine.

See also
- http://jpl7.org/ */
   96% suppress debugging this library
   97:- set_prolog_flag(generate_debug_info, false).
 jpl_new(+X, +Params, -V) is det
X can be:

If X is an object (non-array) type or descriptor and Params is a list of values or references, then V is the result of an invocation of that type's most specifically-typed constructor to whose respective formal parameters the actual Params are assignable (and assigned).

If X is an array type or descriptor and Params is a list of values or references, each of which is (independently) assignable to the array element type, then V is a new array of as many elements as Params has members, initialised with the respective members of Params.

If X is an array type or descriptor and Params is a non-negative integer N, then V is a new array of that type, with N elements, each initialised to Java's appropriate default value for the type.

If V is {Term} then we attempt to convert a new org.jpl7.Term instance to a corresponding term; this is of little obvious use here, but is consistent with jpl_call/4 and jpl_get/3.

  127jpl_new(X, Params, V) :-
  128    (   var(X)
  129    ->  throw(error(instantiation_error,context(jpl_new/3,'1st arg must be bound to a classname, descriptor or object type')))
  130    ;   jpl_is_type(X)                  % NB only class(_,_) or array(_)
  131    ->  Type = X
  132    ;   atom(X)                 % e.g. 'java.lang.String', '[L', 'boolean'
  133    ->  (   jpl_classname_to_type(X, Type)
  134        ->  true
  135        ;   throw(error(domain_error(classname,X),context(jpl_new/3,'if 1st arg is an atom, it must be a classname or descriptor')))
  136        )
  137    ;   throw(error(type_error(instantiable,X),context(jpl_new/3,'1st arg must be a classname, descriptor or object type')))
  138    ),
  139    jpl_new_1(Type, Params, Vx),
  140    (   nonvar(V),
  141        V = {Term}  % yucky way of requesting Term->term conversion
  142    ->  (   jni_jref_to_term(Vx, TermX)    % fails if Rx is not a JRef to a org.jpl7.Term
  143        ->  Term = TermX
  144        ;   throw(error(type_error,context(jpl_call/4, 'result is not a org.jpl7.Term instance as required')))
  145        )
  146    ;   V = Vx
  147    ).
 jpl_new_1(+Tx, +Params, -Vx)
(serves only jpl_new/3)

Tx can be a class(_,_) or array(_) type.

Params must be a proper list of constructor parameters.

At exit, Vx is bound to a JPL reference to a new, initialised instance of Tx

  160jpl_new_1(class(Ps,Cs), Params, Vx) :-
  161    !,                                      % green (see below)
  162    Tx = class(Ps,Cs),
  163    (   var(Params)
  164    ->  throw(error(instantiation_error,context(jpl_new/3,'2nd arg must be a proper list of valid parameters for a constructor')))
  165    ;   \+ is_list(Params)
  166    ->  throw(error(type_error(list,Params),context(jpl_new/3,'2nd arg must be a proper list of valid parameters for a constructor')))
  167    ;   true
  168    ),
  169    length(Params, A),          % the "arity" of the required constructor
  170    jpl_type_to_class(Tx, Cx),  % throws Java exception if class is not found
  171    N = '<init>',               % JNI's constructor naming convention for GetMethodID()
  172    Tr = void,                  % all constructors have this return "type"
  173    findall(
  174        z3(I,MID,Tfps),
  175        jpl_method_spec(Tx, I, N, A, _Mods, MID, Tr, Tfps), % cached
  176        Z3s
  177    ),
  178    (   Z3s == []               % no constructors which require the given qty of parameters?
  179    ->  jpl_type_to_classname(Tx, Cn),
  180        (   jpl_call(Cx, isInterface, [], @(true))
  181        ->  throw(error(type_error(concrete_class,Cn),context(jpl_new/3,'cannot create instance of an interface')))
  182        ;   throw(error(existence_error(constructor,Cn/A),context(jpl_new/3,'no constructor found with the corresponding quantity of parameters')))
  183        )
  184    ;   (   catch(
  185                jpl_datums_to_types(Params, Taps),  % infer actual parameter types
  186                error(type_error(acyclic,Te),context(jpl_datum_to_type/2,Msg)),
  187                throw(error(type_error(acyclic,Te),context(jpl_new/3,Msg)))
  188            )
  189        ->  true
  190        ;   throw(error(domain_error(list(jpl_datum),Params),context(jpl_new/3,'one or more of the actual parameters is not a valid representation of any Java value or object')))
  191        ),
  192        findall(
  193            z3(I,MID,Tfps),                 % select constructors to which actual parameters are assignable
  194            (   member(z3(I,MID,Tfps), Z3s),
  195                jpl_types_fit_types(Taps, Tfps) % assignability test: actual parameter types "fit" formal parameter types?
  196            ),
  197            Z3sA
  198        ),
  199        (   Z3sA == []                      % no type-assignable constructors?
  200        ->  (   Z3s = [_]
  201            ->  throw(error(existence_error(constructor,Tx/A),context(jpl_new/3,'the actual parameters are not assignable to the formal parameter types of the only constructor which takes this qty of parameters')))
  202            ;   throw(error(type_error(constructor_args,Params),context(jpl_new/3,'the actual parameters are not assignable to the formal parameter types of any of the constructors which take this qty of parameters')))
  203            )
  204        ;   Z3sA = [z3(I,MID,Tfps)]
  205        ->  true
  206        ;   jpl_z3s_to_most_specific_z3(Z3sA, z3(I,MID,Tfps))
  207        ->  true
  208        ;   throw(error(type_error(constructor_params,Params),context(jpl_new/3,'more than one most-specific matching constructor (shouldn''t happen)')))
  209        )
  210    ),
  211    catch(
  212        jNewObject(Cx, MID, Tfps, Params, Vx),
  213        error(java_exception(_), 'java.lang.InstantiationException'),
  214        (   jpl_type_to_classname(Tx, Cn),
  215            throw(error(type_error(concrete_class,Cn),context(jpl_new/3,'cannot create instance of an abstract class')))
  216        )
  217    ),
  218    jpl_cache_type_of_ref(Tx, Vx).          % since we know it
  219jpl_new_1(array(T), Params, Vx) :-
  220    !,
  221    (   var(Params)
  222    ->  throw(error(instantiation_error,context(jpl_new/3,'when constructing a new array, 2nd arg must either be a non-negative integer (denoting the required array length) or a proper list of valid element values')))
  223    ;   integer(Params)         % integer I -> array[0..I-1] of default values
  224    ->  (   Params >= 0
  225        ->  Len is Params
  226        ;   throw(error(domain_error(array_length,Params),context(jpl_new/3,'when constructing a new array, if the 2nd arg is an integer (denoting the required array length) then it must be non-negative')))
  227        )
  228    ;   is_list(Params)     % [V1,..VN] -> array[0..N-1] of respective values
  229    ->  length(Params, Len)
  230    ),
  231    jpl_new_array(T, Len, Vx), % NB may throw out-of-memory exception
  232    (   nth0(I, Params, Param),     % nmember fails silently when Params is integer
  233        jpl_set(Vx, I, Param),
  234        fail
  235    ;   true
  236    ),
  237    jpl_cache_type_of_ref(array(T), Vx).   % since we know it
  238jpl_new_1(T, _Params, _Vx) :-       % doomed attempt to create new primitive type instance (formerly a dubious completist feature :-)
  239    jpl_primitive_type(T),
  240    !,
  241    throw(error(domain_error(object_type,T),context(jpl_new/3,'cannot construct an instance of a primitive type'))).
  242  % (   var(Params)
  243  % ->  throw(error(instantiation_error,
  244  %                 context(jpl_new/3,
  245  %                         'when constructing a new instance of a primitive type, 2nd arg must be bound (to a representation of a suitable value)')))
  246  % ;   Params == []
  247  % ->  jpl_primitive_type_default_value(T, Vx)
  248  % ;   Params = [Param]
  249  % ->  jpl_primitive_type_term_to_value(T, Param, Vx)
  250  % ;   throw(error(domain_error(constructor_args,Params),
  251  %                 context(jpl_new/3,
  252  %                         'when constructing a new instance of a primitive type, 2nd arg must either be an empty list (indicating that the default value of that type is required) or a list containing exactly one representation of a suitable value)')))
  253  % ).
  254jpl_new_1(T, _, _) :-
  255    throw(error(domain_error(jpl_type,T),context(jpl_new/3,'1st arg must denote a known or plausible type'))).
 jpl_new_array(+ElementType, +Length, -NewArray) is det
binds NewArray to a jref to a newly created Java array of ElementType and Length
  262jpl_new_array(boolean, Len, A) :-
  263    jNewBooleanArray(Len, A).
  264jpl_new_array(byte, Len, A) :-
  265    jNewByteArray(Len, A).
  266jpl_new_array(char, Len, A) :-
  267    jNewCharArray(Len, A).
  268jpl_new_array(short, Len, A) :-
  269    jNewShortArray(Len, A).
  270jpl_new_array(int, Len, A) :-
  271    jNewIntArray(Len, A).
  272jpl_new_array(long, Len, A) :-
  273    jNewLongArray(Len, A).
  274jpl_new_array(float, Len, A) :-
  275    jNewFloatArray(Len, A).
  276jpl_new_array(double, Len, A) :-
  277    jNewDoubleArray(Len, A).
  278jpl_new_array(array(T), Len, A) :-
  279    jpl_type_to_class(array(T), C),
  280    jNewObjectArray(Len, C, @(null), A).        % initialise each element to null
  281jpl_new_array(class(Ps,Cs), Len, A) :-
  282    jpl_type_to_class(class(Ps,Cs), C),
  283    jNewObjectArray(Len, C, @(null), A).
 jpl_call(+X, +MethodName:atom, +Params:list(datum), -Result:datum) is det
X should be either

MethodName should be a method name (as an atom) (may involve dynamic overload resolution based on inferred types of params)

Params should be a proper list (perhaps empty) of suitable actual parameters for the named method.

The class or object may have several methods with the given name; JPL will resolve (per call) to the most appropriate method based on the quantity and inferred types of Params. This resolution mimics the corresponding static resolution performed by Java compilers.

Finally, an attempt will be made to unify Result with the method's returned value, or with @(void) if it has none.

  305jpl_call(X, Mspec, Params, R) :-
  306    (   jpl_object_to_type(X, Type)         % the usual case (goal fails safely if X is var or rubbish)
  307    ->  Obj = X,
  308        Kind = instance
  309    ;   var(X)
  310    ->  throw(error(instantiation_error,context(jpl_call/4,'1st arg must be bound to an object, classname, descriptor or type')))
  311    ;   atom(X)
  312    ->  (   jpl_classname_to_type(X, Type)     % does this attempt to load the class?
  313        ->  (   jpl_type_to_class(Type, ClassObj)
  314            ->  Kind = static
  315            ;   throw(error(existence_error(class,X),context(jpl_call/4,'the named class cannot be found')))
  316            )
  317        ;   throw(error(type_error(class_name_or_descriptor,X),context(jpl_call/4,'1st arg must be an object, classname, descriptor or type')))
  318        )
  319    ;   X = class(_,_)
  320    ->  Type = X,
  321        jpl_type_to_class(Type, ClassObj),
  322        Kind = static
  323    ;   X = array(_)
  324    ->  throw(error(type_error(object_or_class,X),context(jpl_call/4,'cannot call a static method of an array type, as none exists')))
  325    ;   throw(error(domain_error(object_or_class,X),context(jpl_call/4,'1st arg must be an object, classname, descriptor or type')))
  326    ),
  327    (   atom(Mspec)                 % the usual case, i.e. a method name
  328    ->  true
  329    ;   var(Mspec)
  330    ->  throw(error(instantiation_error,context(jpl_call/4,'2nd arg must be an atom naming a public method of the class or object')))
  331    ;   throw(error(type_error(method_name,Mspec),context(jpl_call/4,'2nd arg must be an atom naming a public method of the class or object')))
  332    ),
  333    (   is_list(Params)
  334    ->  (   catch(
  335                jpl_datums_to_types(Params, Taps),
  336                error(type_error(acyclic,Te),context(jpl_datum_to_type/2,Msg)),
  337                throw(error(type_error(acyclic,Te),context(jpl_call/4,Msg)))
  338            )
  339        ->  true
  340        ;   throw(error(type_error(method_params,Params),context(jpl_call/4,'not all actual parameters are convertible to Java values or references')))
  341        ),
  342        length(Params, A)
  343    ;   var(Params)
  344    ->  throw(error(instantiation_error,context(jpl_call/4,'3rd arg must be a proper list of actual parameters for the named method')))
  345    ;   throw(error(type_error(method_params,Params),context(jpl_call/4,'3rd arg must be a proper list of actual parameters for the named method')))
  346    ),
  347    (   Kind == instance
  348    ->  jpl_call_instance(Type, Obj, Mspec, Params, Taps, A, Rx)
  349    ;   jpl_call_static(Type, ClassObj, Mspec, Params, Taps, A, Rx)
  350    ),
  351    (   nonvar(R),
  352        R = {Term}  % yucky way of requesting Term->term conversion
  353    ->  (   jni_jref_to_term(Rx, TermX)    % fails if Rx isn't a JRef to a org.jpl7.Term
  354        ->  Term = TermX
  355        ;   throw(error(type_error,context(jpl_call/4,'result is not a org.jpl7.Term instance as required')))
  356        )
  357    ;   R = Rx
  358    ).
 jpl_call_instance(+ObjectType, +Object, +MethodName, +Params, +ActualParamTypes, +Arity, -Result)
calls the MethodName-d method (instance or static) of Object (which is of ObjectType), which most specifically applies to Params, which we have found to be (respectively) of ActualParamTypes, and of which there are Arity, yielding Result.
  368jpl_call_instance(Type, Obj, Mname, Params, Taps, A, Rx) :-
  369    findall(                    % get remaining details of all accessible methods of Obj's class (as denoted by Type)
  370        z5(I,Mods,MID,Tr,Tfps),
  371        jpl_method_spec(Type, I, Mname, A, Mods, MID, Tr, Tfps),
  372        Z5s
  373    ),
  374    (   Z5s = []
  375    ->  throw(error(existence_error(method,Mname/A),context(jpl_call/4,'the class or object has no public methods with the given name and quantity of parameters')))
  376    ;   findall(
  377            z5(I,Mods,MID,Tr,Tfps),             % those to which Params is assignable
  378            (   member(z5(I,Mods,MID,Tr,Tfps), Z5s),
  379                jpl_types_fit_types(Taps, Tfps) % assignability test: actual param types "fit" formal param types
  380            ),
  381            Z5sA                                % Params-assignable methods
  382        ),
  383        (   Z5sA == []
  384        ->  throw(error(type_error(method_params,Params),context(jpl_call/4,'the actual parameters are not assignable to the formal parameters of any of the named methods')))
  385        ;   Z5sA = [z5(I,Mods,MID,Tr,Tfps)]
  386        ->  true                                % exactly one applicable method
  387        ;   jpl_z5s_to_most_specific_z5(Z5sA, z5(I,Mods,MID,Tr,Tfps))
  388        ->  true                                % exactly one most-specific applicable method
  389        ;   throw(error(existence_error(most_specific_method,Mname/Params),context(jpl_call/4,'more than one most-specific method is found for the actual parameters (this should not happen)')))
  390        )
  391    ),
  392    (   member(static, Mods)                                        % if the chosen method is static
  393    ->  jpl_object_to_class(Obj, ClassObj),                         % get a java.lang.Class instance which personifies Obj's class
  394        jpl_call_static_method(Tr, ClassObj, MID, Tfps, Params, Rx) % call static method w.r.t. associated Class object
  395    ;   jpl_call_instance_method(Tr, Obj, MID, Tfps, Params, Rx)    % else call (non-static) method w.r.t. object itself
  396    ).
 jpl_call_static(+ClassType, +ClassObject, +MethodName, +Params, +ActualParamTypes, +Arity, -Result)
calls the MethodName-d static method of the class (which is of ClassType, and which is represented by the java.lang.Class instance ClassObject) which most specifically applies to Params, which we have found to be (respectively) of ActualParamTypes, and of which there are Arity, yielding Result.
  407jpl_call_static(Type, ClassObj, Mname, Params, Taps, A, Rx) :-
  408    findall(                    % get all accessible static methods of the class denoted by Type and ClassObj
  409        z5(I,Mods,MID,Tr,Tfps),
  410        (   jpl_method_spec(Type, I, Mname, A, Mods, MID, Tr, Tfps),
  411            member(static, Mods)
  412        ),
  413        Z5s
  414    ),
  415    (   Z5s = []
  416    ->  throw(error(existence_error(method,Mname/A),context(jpl_call/4,'the class has no public static methods with the given name and quantity of parameters')))
  417    ;   findall(
  418            z5(I,Mods,MID,Tr,Tfps),
  419            (   member(z5(I,Mods,MID,Tr,Tfps), Z5s),
  420                jpl_types_fit_types(Taps, Tfps) % assignability test: actual param types "fit" formal param types
  421            ),
  422            Z5sA                                % Params-assignable methods
  423        ),
  424        (   Z5sA == []
  425        ->  throw(error(type_error(method_params,Params),context(jpl_call/4,'the actual parameters are not assignable to the formal parameters of any of the named methods')))
  426        ;   Z5sA = [z5(I,Mods,MID,Tr,Tfps)]
  427        ->  true                % exactly one applicable method
  428        ;   jpl_z5s_to_most_specific_z5(Z5sA, z5(I,Mods,MID,Tr,Tfps))
  429        ->  true                % exactly one most-specific applicable method
  430        ;   throw(error(existence_error(most_specific_method,Mname/Params),context(jpl_call/4,'more than one most-specific method is found for the actual parameters (this should not happen)')))
  431        )
  432    ),
  433    jpl_call_static_method(Tr, ClassObj, MID, Tfps, Params, Rx).
 jpl_call_instance_method(+Type, +ClassObject, +MethodID, +FormalParamTypes, +Params, -Result)
  438jpl_call_instance_method(void, Class, MID, Tfps, Ps, R) :-
  439    jCallVoidMethod(Class, MID, Tfps, Ps),
  440    jpl_void(R).
  441jpl_call_instance_method(boolean, Class, MID, Tfps, Ps, R) :-
  442    jCallBooleanMethod(Class, MID, Tfps, Ps, R).
  443jpl_call_instance_method(byte, Class, MID, Tfps, Ps, R) :-
  444    jCallByteMethod(Class, MID, Tfps, Ps, R).
  445jpl_call_instance_method(char, Class, MID, Tfps, Ps, R) :-
  446    jCallCharMethod(Class, MID, Tfps, Ps, R).
  447jpl_call_instance_method(short, Class, MID, Tfps, Ps, R) :-
  448    jCallShortMethod(Class, MID, Tfps, Ps, R).
  449jpl_call_instance_method(int, Class, MID, Tfps, Ps, R) :-
  450    jCallIntMethod(Class, MID, Tfps, Ps, R).
  451jpl_call_instance_method(long, Class, MID, Tfps, Ps, R) :-
  452    jCallLongMethod(Class, MID, Tfps, Ps, R).
  453jpl_call_instance_method(float, Class, MID, Tfps, Ps, R) :-
  454    jCallFloatMethod(Class, MID, Tfps, Ps, R).
  455jpl_call_instance_method(double, Class, MID, Tfps, Ps, R) :-
  456    jCallDoubleMethod(Class, MID, Tfps, Ps, R).
  457jpl_call_instance_method(array(_), Class, MID, Tfps, Ps, R) :-
  458    jCallObjectMethod(Class, MID, Tfps, Ps, R).
  459jpl_call_instance_method(class(_,_), Class, MID, Tfps, Ps, R) :-
  460    jCallObjectMethod(Class, MID, Tfps, Ps, R).
 jpl_call_static_method(+Type, +ClassObject, +MethodID, +FormalParamTypes, +Params, -Result)
  465jpl_call_static_method(void, Class, MID, Tfps, Ps, R) :-
  466    jCallStaticVoidMethod(Class, MID, Tfps, Ps),
  467    jpl_void(R).
  468jpl_call_static_method(boolean, Class, MID, Tfps, Ps, R) :-
  469    jCallStaticBooleanMethod(Class, MID, Tfps, Ps, R).
  470jpl_call_static_method(byte, Class, MID, Tfps, Ps, R) :-
  471    jCallStaticByteMethod(Class, MID, Tfps, Ps, R).
  472jpl_call_static_method(char, Class, MID, Tfps, Ps, R) :-
  473    jCallStaticCharMethod(Class, MID, Tfps, Ps, R).
  474jpl_call_static_method(short, Class, MID, Tfps, Ps, R) :-
  475    jCallStaticShortMethod(Class, MID, Tfps, Ps, R).
  476jpl_call_static_method(int, Class, MID, Tfps, Ps, R) :-
  477    jCallStaticIntMethod(Class, MID, Tfps, Ps, R).
  478jpl_call_static_method(long, Class, MID, Tfps, Ps, R) :-
  479    jCallStaticLongMethod(Class, MID, Tfps, Ps, R).
  480jpl_call_static_method(float, Class, MID, Tfps, Ps, R) :-
  481    jCallStaticFloatMethod(Class, MID, Tfps, Ps, R).
  482jpl_call_static_method(double, Class, MID, Tfps, Ps, R) :-
  483    jCallStaticDoubleMethod(Class, MID, Tfps, Ps, R).
  484jpl_call_static_method(array(_), Class, MID, Tfps, Ps, R) :-
  485    jCallStaticObjectMethod(Class, MID, Tfps, Ps, R).
  486jpl_call_static_method(class(_,_), Class, MID, Tfps, Ps, R) :-
  487    jCallStaticObjectMethod(Class, MID, Tfps, Ps, R).
 jpl_get(+X, +Fspec, -V:datum) is det
X can be

Fspec can be

Finally, an attempt will be made to unify V with the retrieved value or object reference.

Examples

jpl_get('java.awt.Cursor', 'NE_RESIZE_CURSOR', Q).
Q = 7.

jpl_new(array(class([java,lang],['String'])), [for,while,do,if,then,else,try,catch,finally], A),
jpl_get(A, 3-5, B).
B = [if, then, else].
  519jpl_get(X, Fspec, V) :-
  520    (   jpl_object_to_type(X, Type)
  521    ->  Obj = X,
  522        jpl_get_instance(Type, Type, Obj, Fspec, Vx)   % pass Type twice for FAI
  523    ;   var(X)
  524    ->  throw(error(instantiation_error,context(jpl_get/3,'1st arg must be bound to an object, classname, descriptor or type')))
  525    ;   jpl_is_type(X)          % e.g. class([java,lang],['String']), array(int)
  526    ->  Type = X,
  527        (   jpl_type_to_class(Type, ClassObj)
  528        ->  jpl_get_static(Type, ClassObj, Fspec, Vx)
  529        ;   jpl_type_to_classname(Type, Classname),
  530            throw(error(existence_error(class,Classname),context(jpl_get/3,'the named class cannot be found')))
  531        )
  532    ;   atom(X)
  533    ->  (   jpl_classname_to_type(X, Type)     % does this attempt to load the class?
  534        ->  (   jpl_type_to_class(Type, ClassObj)
  535            ->  jpl_get_static(Type, ClassObj, Fspec, Vx)
  536            ;   throw(error(existence_error(class,X),context(jpl_get/3,'the named class cannot be found')))
  537            )
  538        ;   throw(error(type_error(class_name_or_descriptor,X),context(jpl_get/3, '1st arg must be an object, classname, descriptor or type')))
  539        )
  540    ;   throw(error(domain_error(object_or_class,X),context(jpl_get/3,'1st arg must be bound to an object, classname, descriptor or type')))
  541    ),
  542    (   nonvar(V),
  543        V = {Term}  % yucky way of requesting Term->term conversion
  544    ->  (   jni_jref_to_term(Vx, TermX)    % fails if Rx is not a JRef to a org.jpl7.Term
  545        ->  Term = TermX
  546        ;   throw(error(type_error,context(jpl_call/4,'result is not a org.jpl7.Term instance as required')))
  547        )
  548    ;   V = Vx
  549    ).
 jpl_get_static(+Type:type, +ClassObject:jref, +FieldName:atom, -Value:datum) is det
ClassObject is an instance of java.lang.Class which represents the same class as Type; Value (Vx below) is guaranteed unbound on entry, and will, before exit, be unified with the retrieved value
  559jpl_get_static(Type, ClassObj, Fname, Vx) :-
  560    (   atom(Fname)             % assume it's a field name
  561    ->  true
  562    ;   var(Fname)
  563    ->  throw(error(instantiation_error,context(jpl_get/3,'2nd arg must be bound to an atom naming a public field of the class')))
  564    ;   throw(error(type_error(field_name,Fname),context(jpl_get/3,'2nd arg must be an atom naming a public field of the class')))
  565    ),
  566  % get static fields of the denoted class
  567    findall(
  568        z4(I,Mods,FID,Tf),
  569        (   jpl_field_spec(Type, I, Fname, Mods, FID, Tf),
  570            member(static, Mods)
  571        ),
  572        Z4s
  573    ),
  574    (   Z4s = []
  575    ->  throw(error(existence_error(field,Fname),context(jpl_get/3,'the class or object has no public static field with the given name')))
  576    ;   Z4s = [z4(I,_Mods,FID,Tf)]
  577    ->  jpl_get_static_field(Tf, ClassObj, FID, Vx)
  578    ;   throw(error(existence_error(unique_field,Fname),context(jpl_get/3,'more than one field is found with the given name')))
  579    ).
 jpl_get_instance(+Type, +Type, +Object, +FieldSpecifier, -Value) is det
  584jpl_get_instance(class(_,_), Type, Obj, Fname, Vx) :-
  585    (   atom(Fname)                 % the usual case
  586    ->  true
  587    ;   var(Fname)
  588    ->  throw(error(instantiation_error,context(jpl_get/3,'2nd arg must be bound to an atom naming a public field of the class or object')))
  589    ;   throw(error(type_error(field_name,Fname),context(jpl_get/3,'2nd arg must be an atom naming a public field of the class or object')))
  590    ),
  591    findall(
  592        z4(I,Mods,FID,Tf),
  593        jpl_field_spec(Type, I, Fname, Mods, FID, Tf),
  594        Z4s
  595    ),
  596    (   Z4s = []
  597    ->  throw(error(existence_error(field,Fname),context(jpl_get/3,'the class or object has no public field with the given name')))
  598    ;   Z4s = [z4(I,Mods,FID,Tf)]
  599    ->  (   member(static, Mods)
  600        ->  jpl_object_to_class(Obj, ClassObj),
  601            jpl_get_static_field(Tf, ClassObj, FID, Vx)
  602        ;   jpl_get_instance_field(Tf, Obj, FID, Vx)
  603        )
  604    ;   throw(error(existence_error(unique_field,Fname),context(jpl_get/3,'more than one field is found with the given name')))
  605    ).
  606jpl_get_instance(array(ElementType), _, Array, Fspec, Vx) :-
  607    (   var(Fspec)
  608    ->  throw(error(instantiation_error,context(jpl_get/3,'when 1st arg is an array, 2nd arg must be bound to an index, an index range, or ''length''')))
  609    ;   integer(Fspec)
  610    ->  (   Fspec < 0       % lo bound check
  611        ->  throw(error(domain_error(array_index,Fspec),context(jpl_get/3,'when 1st arg is an array, integral 2nd arg must be non-negative')))
  612        ;   jGetArrayLength(Array, Len),
  613            Fspec >= Len    % hi bound check
  614        ->  throw(error(domain_error(array_index,Fspec),context(jpl_get/3,'when 1st arg is an array, integral 2nd arg must not exceed upper bound of array')))
  615        ;   jpl_get_array_element(ElementType, Array, Fspec, Vx)
  616        )
  617    ;   Fspec = N-M     % NB should we support e.g. 3-2 -> [] ?
  618    ->  (   integer(N),
  619            integer(M)
  620        ->  (   N >= 0,
  621                M >= N
  622            ->  jGetArrayLength(Array, Len),
  623                (   N >= Len
  624                ->  throw(error(domain_error(array_index_range,N-M),context(jpl_get/3,'lower bound of array index range must not exceed upper bound of array')))
  625                ;   M >= Len
  626                ->  throw(error(domain_error(array_index_range,N-M),context(jpl_get/3,'upper bound of array index range must not exceed upper bound of array')))
  627                ;   jpl_get_array_elements(ElementType, Array, N, M, Vx)
  628                )
  629            ;   throw(error(domain_error(array_index_range,N-M),context(jpl_get/3,'array index range must be a non-decreasing pair of non-negative integers')))
  630            )
  631        ;   throw(error(type_error(array_index_range,N-M),context(jpl_get/3,'array index range must be a non-decreasing pair of non-negative integers')))
  632        )
  633    ;   atom(Fspec)
  634    ->  (   Fspec == length             % special-case for this solitary array "method"
  635        ->  jGetArrayLength(Array, Vx)
  636        ;   throw(error(domain_error(array_field_name,Fspec),context(jpl_get/3,'the array has no public field with the given name')))
  637        )
  638    ;   throw(error(type_error(array_lookup_spec,Fspec),context(jpl_get/3,'when 1st arg is an array, 2nd arg must be an index, an index range, or ''length''')))
  639    ).
 jpl_get_array_element(+ElementType:type, +Array:jref, +Index, -Vc) is det
Array is a JPL reference to a Java array of ElementType; Vc is (unified with a JPL repn of) its Index-th (numbered from 0) element Java values are now converted to Prolog terms within foreign code
To be done
- more of this could be done within foreign code
  651jpl_get_array_element(Type, Array, Index, Vc) :-
  652    (   (   Type = class(_,_)
  653        ;   Type = array(_)
  654        )
  655    ->  jGetObjectArrayElement(Array, Index, Vr)
  656    ;   jpl_primitive_type(Type)
  657    ->  jni_type_to_xput_code(Type, Xc),
  658        jni_alloc_buffer(Xc, 1, Bp),        % one-element buf for a Type
  659        jpl_get_primitive_array_region(Type, Array, Index, 1, Bp),
  660        jni_fetch_buffer_value(Bp, 0, Vr, Xc),    % zero-th element
  661        jni_free_buffer(Bp)
  662    ),
  663    Vr = Vc.    % redundant since Vc is always (?) unbound at call
 jpl_get_array_elements(+ElementType, +Array, +N, +M, -Vs)
serves only jpl_get_instance/5

Vs will always be unbound on entry

  672jpl_get_array_elements(ElementType, Array, N, M, Vs) :-
  673    (   (   ElementType = class(_,_)
  674        ;   ElementType = array(_)
  675        )
  676    ->  jpl_get_object_array_elements(Array, N, M, Vs)
  677    ;   jpl_get_primitive_array_elements(ElementType, Array, N, M, Vs)
  678    ).
  679
  680
  681jpl_get_instance_field(boolean, Obj, FieldID, V) :-
  682    jGetBooleanField(Obj, FieldID, V).
  683jpl_get_instance_field(byte, Obj, FieldID, V) :-
  684    jGetByteField(Obj, FieldID, V).
  685jpl_get_instance_field(char, Obj, FieldID, V) :-
  686    jGetCharField(Obj, FieldID, V).
  687jpl_get_instance_field(short, Obj, FieldID, V) :-
  688    jGetShortField(Obj, FieldID, V).
  689jpl_get_instance_field(int, Obj, FieldID, V) :-
  690    jGetIntField(Obj, FieldID, V).
  691jpl_get_instance_field(long, Obj, FieldID, V) :-
  692    jGetLongField(Obj, FieldID, V).
  693jpl_get_instance_field(float, Obj, FieldID, V) :-
  694    jGetFloatField(Obj, FieldID, V).
  695jpl_get_instance_field(double, Obj, FieldID, V) :-
  696    jGetDoubleField(Obj, FieldID, V).
  697jpl_get_instance_field(class(_,_), Obj, FieldID, V) :-
  698    jGetObjectField(Obj, FieldID, V).
  699jpl_get_instance_field(array(_), Obj, FieldID, V) :-
  700    jGetObjectField(Obj, FieldID, V).
 jpl_get_object_array_elements(+Array, +LoIndex, +HiIndex, -Vcs) is det
Array should be a (zero-based) array of some object (array or non-array) type; LoIndex is an integer, 0 =< LoIndex < length(Array); HiIndex is an integer, LoIndex-1 =< HiIndex < length(Array); at call, Vcs will be unbound; at exit, Vcs will be a list of (references to) the array's elements [LoIndex..HiIndex] inclusive
  712jpl_get_object_array_elements(Array, Lo, Hi, Vcs) :-
  713    (   Lo =< Hi
  714    ->  Vcs = [Vc|Vcs2],
  715        jGetObjectArrayElement(Array, Lo, Vc),
  716        Next is Lo+1,
  717        jpl_get_object_array_elements(Array, Next, Hi, Vcs2)
  718    ;   Vcs = []
  719    ).
 jpl_get_primitive_array_elements(+ElementType, +Array, +LoIndex, +HiIndex, -Vcs) is det
Array should be a (zero-based) Java array of (primitive) ElementType; Vcs should be unbound on entry, and on exit will be a list of (JPL representations of the values of) the elements [LoIndex..HiIndex] inclusive
  729jpl_get_primitive_array_elements(ElementType, Array, Lo, Hi, Vcs) :-
  730    Size is Hi-Lo+1,
  731    (   Size == 0
  732    ->  Vcs = []
  733    ;   jni_type_to_xput_code(ElementType, Xc),
  734        jni_alloc_buffer(Xc, Size, Bp),
  735        jpl_get_primitive_array_region(ElementType, Array, Lo, Size, Bp),
  736        jpl_primitive_buffer_to_array(ElementType, Xc, Bp, 0, Size, Vcs),
  737        jni_free_buffer(Bp)
  738    ).
  739
  740
  741jpl_get_primitive_array_region(boolean, Array, Lo, S, I) :-
  742    jGetBooleanArrayRegion(Array, Lo, S, jbuf(I,boolean)).
  743jpl_get_primitive_array_region(byte, Array, Lo, S, I) :-
  744    jGetByteArrayRegion(Array, Lo, S, jbuf(I,byte)).
  745jpl_get_primitive_array_region(char, Array, Lo, S, I) :-
  746    jGetCharArrayRegion(Array, Lo, S, jbuf(I,char)).
  747jpl_get_primitive_array_region(short, Array, Lo, S, I) :-
  748    jGetShortArrayRegion(Array, Lo, S, jbuf(I,short)).
  749jpl_get_primitive_array_region(int, Array, Lo, S, I) :-
  750    jGetIntArrayRegion(Array, Lo, S, jbuf(I,int)).
  751jpl_get_primitive_array_region(long, Array, Lo, S, I) :-
  752    jGetLongArrayRegion(Array, Lo, S, jbuf(I,long)).
  753jpl_get_primitive_array_region(float, Array, Lo, S, I) :-
  754    jGetFloatArrayRegion(Array, Lo, S, jbuf(I,float)).
  755jpl_get_primitive_array_region(double, Array, Lo, S, I) :-
  756    jGetDoubleArrayRegion(Array, Lo, S, jbuf(I,double)).
  757
  758
  759jpl_get_static_field(boolean, Array, FieldID, V) :-
  760    jGetStaticBooleanField(Array, FieldID, V).
  761jpl_get_static_field(byte, Array, FieldID, V) :-
  762    jGetStaticByteField(Array, FieldID, V).
  763jpl_get_static_field(char, Array, FieldID, V) :-
  764    jGetStaticCharField(Array, FieldID, V).
  765jpl_get_static_field(short, Array, FieldID, V) :-
  766    jGetStaticShortField(Array, FieldID, V).
  767jpl_get_static_field(int, Array, FieldID, V) :-
  768    jGetStaticIntField(Array, FieldID, V).
  769jpl_get_static_field(long, Array, FieldID, V) :-
  770    jGetStaticLongField(Array, FieldID, V).
  771jpl_get_static_field(float, Array, FieldID, V) :-
  772    jGetStaticFloatField(Array, FieldID, V).
  773jpl_get_static_field(double, Array, FieldID, V) :-
  774    jGetStaticDoubleField(Array, FieldID, V).
  775jpl_get_static_field(class(_,_), Array, FieldID, V) :-
  776    jGetStaticObjectField(Array, FieldID, V).
  777jpl_get_static_field(array(_), Array, FieldID, V) :-
  778    jGetStaticObjectField(Array, FieldID, V).
 jpl_set(+X, +Fspec, +V) is det
sets the Fspec-th field of (class or object) X to value V iff it is assignable

X can be

Fspec can be

V must be a suitable value or object.

  798jpl_set(X, Fspec, V) :-
  799    (   jpl_object_to_type(X, Type)         % the usual case (test is safe if X is var or rubbish)
  800    ->  Obj = X,
  801        catch(
  802            jpl_set_instance(Type, Type, Obj, Fspec, V),    % first 'Type' is for FAI
  803            error(type_error(acyclic,Te),context(jpl_datum_to_type/2,Msg)),
  804            throw(error(type_error(acyclic,Te),context(jpl_set/3,Msg)))
  805        )
  806    ;   var(X)
  807    ->  throw(error(instantiation_error,context(jpl_set/3,'1st arg must be an object, classname, descriptor or type')))
  808    ;   (   atom(X)
  809        ->  (   jpl_classname_to_type(X, Type)          % it's a classname or descriptor...
  810            ->  true
  811            ;   throw(error(existence_error(class,X),context(jpl_set/3,'the named class cannot be found')))
  812            )
  813        ;   (   X = class(_,_)                          % it's a class type...
  814            ;   X = array(_)                            % ...or an array type
  815            )
  816        ->  Type = X
  817        ),
  818        (   jpl_type_to_class(Type, ClassObj)      % ...whose Class object is available
  819        ->  true
  820        ;   jpl_type_to_classname(Type, Classname),
  821            throw(error(existence_error(class,Classname),context(jpl_set/3,'the class cannot be found')))
  822        )
  823    ->  catch(
  824            jpl_set_static(Type, ClassObj, Fspec, V),
  825            error(type_error(acyclic,Te),context(jpl_datum_to_type/2,Msg)),
  826            throw(error(type_error(acyclic,Te),context(jpl_set/3,Msg)))
  827        )
  828    ;   throw(error(domain_error(object_or_class,X),context(jpl_set/3,'1st arg must be an object, classname, descriptor or type')))
  829    ).
 jpl_set_instance(+Type, +Type, +ObjectReference, +FieldName, +Value) is det
ObjectReference is a JPL reference to a Java object of the class denoted by Type (which is passed twice for first agument indexing);

FieldName should name a public, non-final (static or non-static) field of this object, but could be anything, and is validated here;

Value should be assignable to the named field, but could be anything, and is validated here

  842jpl_set_instance(class(_,_), Type, Obj, Fname, V) :-    % a non-array object
  843    (   atom(Fname)                 % the usual case
  844    ->  true
  845    ;   var(Fname)
  846    ->  throw(error(instantiation_error,context(jpl_set/3,'2nd arg must be bound to the name of a public, non-final field')))
  847    ;   throw(error(type_error(field_name,Fname),context(jpl_set/3,'2nd arg must be the name of a public, non-final field')))
  848    ),
  849    findall(
  850        z4(I,Mods,FID,Tf),
  851        jpl_field_spec(Type, I, Fname, Mods, FID, Tf),  % public fields of class denoted by Type
  852        Z4s
  853    ),
  854    (   Z4s = []
  855    ->  throw(error(existence_error(field,Fname),context(jpl_set/3,'no public fields of the object have this name')))
  856    ;   Z4s = [z4(I,Mods,FID,Tf)]
  857    ->  (   member(final, Mods)
  858        ->  throw(error(permission_error(modify,final_field,Fname),context(jpl_set/3,'cannot assign a value to a final field (actually you could but I''ve decided not to let you)')))
  859        ;   jpl_datum_to_type(V, Tv)
  860        ->  (   jpl_type_fits_type(Tv, Tf)
  861            ->  (   member(static, Mods)
  862                ->  jpl_object_to_class(Obj, ClassObj),
  863                    jpl_set_static_field(Tf, ClassObj, FID, V)
  864                ;   jpl_set_instance_field(Tf, Obj, FID, V)         % oughta be jpl_set_instance_field?
  865                )
  866            ;   jpl_type_to_nicename(Tf, NNf),
  867                throw(error(type_error(NNf,V),context(jpl_set/3,'the value is not assignable to the named field of the class')))
  868            )
  869        ;   throw(error(type_error(field_value,V),context(jpl_set/3,'3rd arg does not represent any Java value or object')))
  870        )
  871    ;   throw(error(existence_error(field,Fname),context(jpl_set/3,'more than one public field of the object has this name (this should not happen)')))   % 'existence'? or some other sort of error maybe?
  872    ).
  873jpl_set_instance(array(Type), _, Obj, Fspec, V) :-
  874    (   is_list(V)                  % a list of array element values
  875    ->  Vs = V
  876    ;   var(V)
  877    ->  throw(error(instantiation_error,context(jpl_set/3, 'when 1st arg is an array, 3rd arg must be bound to a suitable element value or list of values')))
  878    ;   Vs = [V]                    % a single array element value
  879    ),
  880    length(Vs, Iv),
  881    (   var(Fspec)
  882    ->  throw(error(instantiation_error,context(jpl_set/3,'when 1st arg is an array, 2nd arg must be bound to an index or index range')))
  883    ;   integer(Fspec)          % single-element assignment
  884    ->  (   Fspec < 0
  885        ->  throw(error(domain_error(array_index,Fspec),context(jpl_set/3,'when 1st arg is an array, an integral 2nd arg must be a non-negative index')))
  886        ;   Iv is 1
  887        ->  N is Fspec
  888        ;   Iv is 0
  889        ->  throw(error(domain_error(array_element(Fspec),Vs),context(jpl_set/3,'no values for array element assignment: needs one')))
  890        ;   throw(error(domain_error(array_element(Fspec),Vs),context(jpl_set/3,'too many values for array element assignment: needs one')))
  891        )
  892    ;   Fspec = N-M             % element-sequence assignment
  893    ->  (   integer(N),
  894            integer(M)
  895        ->  (   N >= 0,
  896                Size is (M-N)+1,
  897                Size >= 0
  898            ->  (   Size == Iv
  899                ->  true
  900                ;   Size < Iv
  901                ->  throw(error(domain_error(array_elements(N-M),Vs),context(jpl_set/3,'too few values for array range assignment')))
  902                ;   throw(error(domain_error(array_elements(N-M),Vs),context(jpl_set/3,'too many values for array range assignment')))
  903                )
  904            ;   throw(error(domain_error(array_index_range,N-M),context(jpl_set/3,'array index range must be a non-decreasing pair of non-negative integers')))
  905            )
  906        ;   throw(error(type_error(array_index_range,N-M),context(jpl_set/3,'array index range must be a non-decreasing pair of non-negative integers')))
  907        )
  908    ;   atom(Fspec)
  909    ->  (   Fspec == length
  910        ->  throw(error(permission_error(modify,final_field,length),context(jpl_set/3,'cannot assign a value to a final field')))
  911        ;   throw(error(existence_error(field,Fspec),context(jpl_set/3,'array has no field with that name')))
  912        )
  913    ;   throw(error(domain_error(array_index,Fspec),context(jpl_set/3,'when 1st arg is an array object, 2nd arg must be a non-negative index or index range')))
  914    ),
  915    jpl_set_array(Type, Obj, N, Iv, Vs).
 jpl_set_static(+Type, +ClassObj, +FieldName, +Value) is det
We can rely on:

NB this does not yet handle shadowed fields correctly.

  930jpl_set_static(Type, ClassObj, Fname, V) :-
  931    (   atom(Fname)                     % the usual case
  932    ->  true
  933    ;   var(Fname)
  934    ->  throw(error(instantiation_error,context(jpl_set/3,'when 1st arg denotes a class, 2nd arg must be bound to the name of a public, static, non-final field')))
  935    ;   throw(error(type_error(field_name,Fname),context(jpl_set/3,'when 1st arg denotes a class, 2nd arg must be the name of a public, static, non-final field')))
  936    ),
  937    findall(  % get all static fields of the denoted class
  938        z4(I,Mods,FID,Tf),
  939        (   jpl_field_spec(Type, I, Fname, Mods, FID, Tf),
  940            member(static, Mods)
  941        ),
  942        Z4s
  943    ),
  944    (   Z4s = []
  945    ->  throw(error(existence_error(field,Fname),context(jpl_set/3,'class has no public static fields of this name')))
  946    ;   Z4s = [z4(I,Mods,FID,Tf)]       % exactly one synonymous field?
  947    ->  (   member(final, Mods)
  948        ->  throw(error(permission_error(modify,final_field,Fname),context(jpl_set/3,'cannot assign a value to a final field')))
  949        ;   jpl_datum_to_type(V, Tv)
  950        ->  (   jpl_type_fits_type(Tv, Tf)
  951            ->  jpl_set_static_field(Tf, ClassObj, FID, V)
  952            ;   jpl_type_to_nicename(Tf, NNf),
  953                throw(error(type_error(NNf,V),context(jpl_set/3,'the value is not assignable to the named field of the class')))
  954            )
  955        ;   throw(error(type_error(field_value,V),context(jpl_set/3,'3rd arg does not represent any Java value or object')))
  956        )
  957    ;   throw(error(existence_error(field,Fname),context(jpl_set/3,'more than one public static field of the class has this name (this should not happen)(?)')))
  958    ).
 jpl_set_array(+ElementType, +Array, +Offset, +DatumQty, +Datums) is det
Datums, of which there are DatumQty, are stashed in successive elements of Array which is an array of ElementType starting at the Offset-th (numbered from 0) throws error(type_error(acyclic,_),context(jpl_datum_to_type/2,_))
  968jpl_set_array(T, A, N, I, Ds) :-
  969    (   jpl_datums_to_types(Ds, Tds)        % most specialised types of given values
  970    ->  (   jpl_types_fit_type(Tds, T)      % all assignable to element type?
  971        ->  true
  972        ;   throw(error(type_error(array(T),Ds),context(jpl_set/3,'not all values are assignable to the array element type')))
  973        )
  974    ;   throw(error(type_error(array(T),Ds),context(jpl_set/3,'not all values are convertible to Java values or references')))
  975    ),
  976    (   (   T = class(_,_)
  977        ;   T = array(_)                    % array elements are objects
  978        )
  979    ->  (   nth0(J, Ds, D),                 % for each datum
  980            Nd is N+J,                      % compute array index
  981            (   D = {Tq}                    % quoted term?
  982            ->  jni_term_to_jref(Tq, D2)    % convert to a JPL reference to a corresponding org.jpl7.Term object
  983            ;   D = D2
  984            ),
  985            jSetObjectArrayElement(A, Nd, D2),
  986            fail                            % iterate
  987        ;   true
  988        )
  989    ;   jpl_primitive_type(T)               % array elements are primitive values
  990    ->  jni_type_to_xput_code(T, Xc),
  991        jni_alloc_buffer(Xc, I, Bp),        % I-element buf of required primitive type
  992        jpl_set_array_1(Ds, T, 0, Bp),
  993        jpl_set_elements(T, A, N, I, Bp),
  994        jni_free_buffer(Bp)
  995    ;   throw(error(system_error(array_element_type,T),context(jpl_set/3,'array element type is unknown (this should not happen)')))
  996    ).
 jpl_set_array_1(+Values, +Type, +BufferIndex, +BufferPointer) is det
successive members of Values are stashed as (primitive) Type from the BufferIndex-th element (numbered from 0) onwards of the buffer indicated by BufferPointer

NB this could be done more efficiently (?) within foreign code...

 1007jpl_set_array_1([], _, _, _).
 1008jpl_set_array_1([V|Vs], Tprim, Ib, Bp) :-
 1009    jni_type_to_xput_code(Tprim, Xc),
 1010    jni_stash_buffer_value(Bp, Ib, V, Xc),
 1011    Ibnext is Ib+1,
 1012    jpl_set_array_1(Vs, Tprim, Ibnext, Bp).
 1013
 1014
 1015jpl_set_elements(boolean, Obj, N, I, Bp) :-
 1016    jSetBooleanArrayRegion(Obj, N, I, jbuf(Bp,boolean)).
 1017jpl_set_elements(char, Obj, N, I, Bp) :-
 1018    jSetCharArrayRegion(Obj, N, I, jbuf(Bp,char)).
 1019jpl_set_elements(byte, Obj, N, I, Bp) :-
 1020    jSetByteArrayRegion(Obj, N, I, jbuf(Bp,byte)).
 1021jpl_set_elements(short, Obj, N, I, Bp) :-
 1022    jSetShortArrayRegion(Obj, N, I, jbuf(Bp,short)).
 1023jpl_set_elements(int, Obj, N, I, Bp) :-
 1024    jSetIntArrayRegion(Obj, N, I, jbuf(Bp,int)).
 1025jpl_set_elements(long, Obj, N, I, Bp) :-
 1026    jSetLongArrayRegion(Obj, N, I, jbuf(Bp,long)).
 1027jpl_set_elements(float, Obj, N, I, Bp) :-
 1028    jSetFloatArrayRegion(Obj, N, I, jbuf(Bp,float)).
 1029jpl_set_elements(double, Obj, N, I, Bp) :-
 1030    jSetDoubleArrayRegion(Obj, N, I, jbuf(Bp,double)).
 jpl_set_instance_field(+Type, +Obj, +FieldID, +V) is det
We can rely on Type, Obj and FieldID being valid, and on V being assignable (if V is a quoted term then it is converted here)
 1038jpl_set_instance_field(boolean, Obj, FieldID, V) :-
 1039    jSetBooleanField(Obj, FieldID, V).
 1040jpl_set_instance_field(byte, Obj, FieldID, V) :-
 1041    jSetByteField(Obj, FieldID, V).
 1042jpl_set_instance_field(char, Obj, FieldID, V) :-
 1043    jSetCharField(Obj, FieldID, V).
 1044jpl_set_instance_field(short, Obj, FieldID, V) :-
 1045    jSetShortField(Obj, FieldID, V).
 1046jpl_set_instance_field(int, Obj, FieldID, V) :-
 1047    jSetIntField(Obj, FieldID, V).
 1048jpl_set_instance_field(long, Obj, FieldID, V) :-
 1049    jSetLongField(Obj, FieldID, V).
 1050jpl_set_instance_field(float, Obj, FieldID, V) :-
 1051    jSetFloatField(Obj, FieldID, V).
 1052jpl_set_instance_field(double, Obj, FieldID, V) :-
 1053    jSetDoubleField(Obj, FieldID, V).
 1054jpl_set_instance_field(class(_,_), Obj, FieldID, V) :-  % also handles byval term assignments
 1055    (   V = {T}                     % quoted term?
 1056    ->  jni_term_to_jref(T, V2)     % convert to a JPL reference to a corresponding org.jpl7.Term object
 1057    ;   V = V2
 1058    ),
 1059    jSetObjectField(Obj, FieldID, V2).
 1060jpl_set_instance_field(array(_), Obj, FieldID, V) :-
 1061    jSetObjectField(Obj, FieldID, V).
 jpl_set_static_field(+Type, +ClassObj, +FieldID, +V)
We can rely on Type, ClassObj and FieldID being valid, and on V being assignable (if V is a quoted term then it is converted here).
 1069jpl_set_static_field(boolean, Obj, FieldID, V) :-
 1070    jSetStaticBooleanField(Obj, FieldID, V).
 1071jpl_set_static_field(byte, Obj, FieldID, V) :-
 1072    jSetStaticByteField(Obj, FieldID, V).
 1073jpl_set_static_field(char, Obj, FieldID, V) :-
 1074    jSetStaticCharField(Obj, FieldID, V).
 1075jpl_set_static_field(short, Obj, FieldID, V) :-
 1076    jSetStaticShortField(Obj, FieldID, V).
 1077jpl_set_static_field(int, Obj, FieldID, V) :-
 1078    jSetStaticIntField(Obj, FieldID, V).
 1079jpl_set_static_field(long, Obj, FieldID, V) :-
 1080    jSetStaticLongField(Obj, FieldID, V).
 1081jpl_set_static_field(float, Obj, FieldID, V) :-
 1082    jSetStaticFloatField(Obj, FieldID, V).
 1083jpl_set_static_field(double, Obj, FieldID, V) :-
 1084    jSetStaticDoubleField(Obj, FieldID, V).
 1085jpl_set_static_field(class(_,_), Obj, FieldID, V) :-    % also handles byval term assignments
 1086    (   V = {T}                         % quoted term?
 1087    ->  jni_term_to_jref(T, V2)         % convert to a JPL reference to a corresponding org.jpl7.Term object
 1088    ;   V = V2
 1089    ),
 1090    jSetStaticObjectField(Obj, FieldID, V2).
 1091jpl_set_static_field(array(_), Obj, FieldID, V) :-
 1092    jSetStaticObjectField(Obj, FieldID, V).
 jpl_get_default_jvm_opts(-Opts:list(atom)) is det
Returns (as a list of atoms) the options which will be passed to the JVM when it is initialised, e.g. ['-Xrs']
 1100jpl_get_default_jvm_opts(Opts) :-
 1101    jni_get_default_jvm_opts(Opts).
 jpl_set_default_jvm_opts(+Opts:list(atom)) is det
Replaces the default JVM initialisation options with those supplied.
 1108jpl_set_default_jvm_opts(Opts) :-
 1109    is_list(Opts),
 1110    length(Opts, N),
 1111    jni_set_default_jvm_opts(N, Opts).
 jpl_get_actual_jvm_opts(-Opts:list(atom)) is semidet
Returns (as a list of atoms) the options with which the JVM was initialised.

Fails silently if a JVM has not yet been started, and can thus be used to test for this.

 1120jpl_get_actual_jvm_opts(Opts) :-
 1121    jni_get_actual_jvm_opts(Opts).
 1122
 1123
 1124jpl_assert(Fact) :-
 1125    (   jpl_assert_policy(Fact, yes)
 1126    ->  assert(Fact)
 1127    ;   true
 1128    ).
 1129
 1130
 1131jpl_assert_policy(jpl_field_spec_cache(_,_,_,_,_,_), yes).
 1132jpl_assert_policy(jpl_method_spec_cache(_,_,_,_,_,_,_,_), yes).
 1133jpl_assert_policy(jpl_class_tag_type_cache(_,_), yes).
 1134jpl_assert_policy(jpl_classname_type_cache(_,_), yes).
 1135jpl_assert_policy(jpl_iref_type_cache(_,_), no).   % must correspond to JPL_CACHE_TYPE_OF_REF in jpl.c
 1136jpl_assert_policy(jpl_field_spec_is_cached(_), YN) :-
 1137    jpl_assert_policy(jpl_field_spec_cache(_,_,_,_,_,_), YN).
 1138jpl_assert_policy(jpl_method_spec_is_cached(_), YN) :-
 1139    jpl_assert_policy(jpl_method_spec_cache(_,_,_,_,_,_,_,_), YN).
 jpl_tidy_iref_type_cache(+Iref) is det
Delete the cached type info, if any, under Iref.

Called from jpl.c's jni_free_iref() via jni_tidy_iref_type_cache()

 1148jpl_tidy_iref_type_cache(Iref) :-
 1149  % write('[decaching types for iref='), write(Iref), write(']'), nl,
 1150    retractall(jpl_iref_type_cache(Iref,_)),
 1151    true.
 1152
 1153
 1154jpl_fergus_find_candidate([], Candidate, Candidate, []).
 1155jpl_fergus_find_candidate([X|Xs], Candidate0, Candidate, Rest) :-
 1156    (   jpl_fergus_greater(X, Candidate0)
 1157    ->  Candidate1 = X,
 1158        Rest = [Candidate0|Rest1]
 1159    ;   Candidate1 = Candidate0,
 1160        Rest = [X|Rest1]
 1161    ),
 1162    jpl_fergus_find_candidate(Xs, Candidate1, Candidate, Rest1).
 1163
 1164
 1165jpl_fergus_greater(z5(_,_,_,_,Tps1), z5(_,_,_,_,Tps2)) :-
 1166    jpl_types_fit_types(Tps1, Tps2).
 1167jpl_fergus_greater(z3(_,_,Tps1), z3(_,_,Tps2)) :-
 1168    jpl_types_fit_types(Tps1, Tps2).
 jpl_fergus_is_the_greatest(+Xs:list(T), -GreatestX:T)
Xs is a list of things for which jpl_fergus_greater/2 defines a partial ordering; GreatestX is one of those, than which none is greater; fails if there is more than one such; this algorithm was contributed to c.l.p by Fergus Henderson in response to my "there must be a better way" challenge: there was, this is it
 1179jpl_fergus_is_the_greatest([X|Xs], Greatest) :-
 1180    jpl_fergus_find_candidate(Xs, X, Greatest, Rest),
 1181    forall(
 1182        member(R, Rest),
 1183        jpl_fergus_greater(Greatest, R)
 1184    ).
 jpl_z3s_to_most_specific_z3(+Zs, -Z)
Zs is a list of arity-matching, type-suitable z3(I,MID,Tfps).

Z is the single most specific element of Zs, i.e. that than which no other z3/3 has a more specialised signature (fails if there is more than one such).

 1194jpl_z3s_to_most_specific_z3(Zs, Z) :-
 1195    jpl_fergus_is_the_greatest(Zs, Z).
 jpl_z5s_to_most_specific_z5(+Zs, -Z)
Zs is a list of arity-matching, type-suitable z5(I,Mods,MID,Tr,Tfps)

Z is the single most specific element of Zs, i.e. that than which no other z5/5 has a more specialised signature (fails if there is more than one such)

 1205jpl_z5s_to_most_specific_z5(Zs, Z) :-
 1206    jpl_fergus_is_the_greatest(Zs, Z).
 jpl_pl_lib_version(-Version)
Version is the fully qualified version identifier of the in-use Prolog component (jpl.pl) of JPL.

It should exactly match the version identifiers of JPL's C (jpl.c) and Java (jpl.jar) components.

Example

?- jpl_pl_lib_version(V).
V = '7.4.0-alpha'.
 1222jpl_pl_lib_version(VersionString) :-
 1223    jpl_pl_lib_version(Major, Minor, Patch, Status),
 1224    atomic_list_concat([Major,'.',Minor,'.',Patch,'-',Status], VersionString).
 jpl_pl_lib_version(-Major, -Minor, -Patch, -Status)
Major, Minor, Patch and Status are the respective components of the version identifier of the in-use C component (jpl.c) of JPL.

Example

?- jpl:jpl_pl_lib_version(Major, Minor, Patch, Status).
Major = 7,
Minor = 4,
Patch = 0,
Status = alpha.
 1241jpl_pl_lib_version(7, 4, 0, alpha).  % jref as blob
 jpl_c_lib_version(-Version)
Version is the fully qualified version identifier of the in-use C component (jpl.c) of JPL.

It should exactly match the version identifiers of JPL's Prolog (jpl.pl) and Java (jpl.jar) components.

Example

?- jpl_c_lib_version(V).
V = '7.4.0-alpha'.
 jpl_java_lib_version(-Version)
Version is the fully qualified version identifier of the in-use Java component (jpl.jar) of JPL.

Example

?- jpl:jpl_java_lib_version(V).
V = '7.4.0-alpha'.
 jpl_java_lib_version(V)
 1270jpl_java_lib_version(V) :-
 1271    jpl_call('org.jpl7.JPL', version_string, [], V).
 jpl_pl_lib_path(-Path:atom)
 1276jpl_pl_lib_path(Path) :-
 1277    module_property(jpl, file(Path)).
 jpl_c_lib_path(-Path:atom)
 1282jpl_c_lib_path(Path) :-
 1283    shlib:current_library(_, _, Path, jpl, _),
 1284    !.
 jpl_java_lib_path(-Path:atom)
 1289jpl_java_lib_path(Path) :-
 1290    jpl_call('org.jpl7.JPL', jarPath, [], Path).
 1291
 1292
 1293% jpl_type_alfa(0'$) -->        % presumably not allowed
 1294%   "$".                        % given the "inner class" syntax?
 1295
 1296jpl_type_alfa(0'_) -->
 1297    "_",
 1298    !.
 1299jpl_type_alfa(C) -->
 1300    [C], { C>=0'a, C=<0'z },
 1301    !.
 1302jpl_type_alfa(C) -->
 1303    [C], { C>=0'A, C=<0'Z }.
 1304
 1305
 1306jpl_type_alfa_num(C) -->
 1307    jpl_type_alfa(C),
 1308    !.
 1309jpl_type_alfa_num(C) -->
 1310    [C], { C>=0'0, C=<0'9 }.
 1311
 1312
 1313jpl_type_array_classname(array(T)) -->
 1314    "[", jpl_type_classname_2(T).
 1315
 1316
 1317jpl_type_array_descriptor(array(T)) -->
 1318    "[", jpl_type_descriptor_1(T).
 1319
 1320
 1321jpl_type_bare_class_descriptor(class(Ps,Cs)) -->
 1322    jpl_type_slashed_package_parts(Ps), jpl_type_class_parts(Cs).
 1323
 1324
 1325jpl_type_bare_classname(class(Ps,Cs)) -->
 1326    jpl_type_dotted_package_parts(Ps), jpl_type_class_parts(Cs).
 1327
 1328
 1329jpl_type_class_descriptor(class(Ps,Cs)) -->
 1330    "L", jpl_type_bare_class_descriptor(class(Ps,Cs)), ";".
 1331
 1332
 1333jpl_type_class_part(N) -->
 1334    jpl_type_id(N).
 1335
 1336
 1337jpl_type_class_parts([C|Cs]) -->
 1338    jpl_type_class_part(C), jpl_type_inner_class_parts(Cs).
 1339
 1340
 1341jpl_type_classname_1(T) -->
 1342    jpl_type_bare_classname(T),
 1343    !.
 1344jpl_type_classname_1(T) -->
 1345    jpl_type_array_classname(T),
 1346    !.
 1347jpl_type_classname_1(T) -->
 1348    jpl_type_primitive(T).
 1349
 1350
 1351jpl_type_classname_2(T) -->
 1352    jpl_type_delimited_classname(T).
 1353jpl_type_classname_2(T) -->
 1354    jpl_type_array_classname(T).
 1355jpl_type_classname_2(T) -->
 1356    jpl_type_primitive(T).
 1357
 1358
 1359
 1360jpl_type_delimited_classname(Class) -->
 1361    "L", jpl_type_bare_classname(Class), ";".
 1362
 1363
 1364
 1365jpl_type_descriptor_1(T) -->
 1366    jpl_type_primitive(T),
 1367    !.
 1368jpl_type_descriptor_1(T) -->
 1369    jpl_type_class_descriptor(T),
 1370    !.
 1371jpl_type_descriptor_1(T) -->
 1372    jpl_type_array_descriptor(T),
 1373    !.
 1374jpl_type_descriptor_1(T) -->
 1375    jpl_type_method_descriptor(T).
 1376
 1377
 1378
 1379jpl_type_dotted_package_parts([P|Ps]) -->
 1380    jpl_type_package_part(P), ".", !, jpl_type_dotted_package_parts(Ps).
 1381jpl_type_dotted_package_parts([]) -->
 1382    [].
 1383
 1384
 1385
 1386jpl_type_findclassname(T) -->
 1387    jpl_type_bare_class_descriptor(T).
 1388jpl_type_findclassname(T) -->
 1389    jpl_type_array_descriptor(T).
 1390
 1391
 1392
 1393jpl_type_id(A) -->
 1394    { nonvar(A) -> atom_codes(A,[C|Cs]) ; true },
 1395    jpl_type_alfa(C), jpl_type_id_rest(Cs),
 1396    { atom_codes(A, [C|Cs]) }.
 1397
 1398
 1399
 1400jpl_type_id_rest([C|Cs]) -->
 1401    jpl_type_alfa_num(C), !, jpl_type_id_rest(Cs).
 1402jpl_type_id_rest([]) -->
 1403    [].
 1404
 1405
 1406
 1407jpl_type_id_v2(A) -->                   % inner class name parts (empirically)
 1408    { nonvar(A) -> atom_codes(A,Cs) ; true },
 1409    jpl_type_id_rest(Cs),
 1410    { atom_codes(A, Cs) }.
 1411
 1412
 1413
 1414jpl_type_inner_class_part(N) -->
 1415    jpl_type_id_v2(N).
 1416
 1417
 1418
 1419jpl_type_inner_class_parts([C|Cs]) -->
 1420    "$", jpl_type_inner_class_part(C), !, jpl_type_inner_class_parts(Cs).
 1421jpl_type_inner_class_parts([]) -->
 1422    [].
 1423
 1424
 1425
 1426jpl_type_method_descriptor(method(Ts,T)) -->
 1427    "(", jpl_type_method_descriptor_args(Ts), ")", jpl_type_method_descriptor_return(T).
 1428
 1429
 1430
 1431jpl_type_method_descriptor_args([T|Ts]) -->
 1432    jpl_type_descriptor_1(T), !, jpl_type_method_descriptor_args(Ts).
 1433jpl_type_method_descriptor_args([]) -->
 1434    [].
 1435
 1436
 1437
 1438jpl_type_method_descriptor_return(T) -->
 1439    jpl_type_void(T).
 1440jpl_type_method_descriptor_return(T) -->
 1441    jpl_type_descriptor_1(T).
 1442
 1443
 1444
 1445jpl_type_package_part(N) -->
 1446    jpl_type_id(N).
 1447
 1448
 1449
 1450jpl_type_primitive(boolean) -->
 1451    "Z",
 1452    !.
 1453jpl_type_primitive(byte) -->
 1454    "B",
 1455    !.
 1456jpl_type_primitive(char) -->
 1457    "C",
 1458    !.
 1459jpl_type_primitive(short) -->
 1460    "S",
 1461    !.
 1462jpl_type_primitive(int) -->
 1463    "I",
 1464    !.
 1465jpl_type_primitive(long) -->
 1466    "J",
 1467    !.
 1468jpl_type_primitive(float) -->
 1469    "F",
 1470    !.
 1471jpl_type_primitive(double) -->
 1472    "D".
 1473
 1474
 1475
 1476jpl_type_slashed_package_parts([P|Ps]) -->
 1477    jpl_type_package_part(P), "/", !, jpl_type_slashed_package_parts(Ps).
 1478jpl_type_slashed_package_parts([]) -->
 1479    [].
 1480
 1481
 1482
 1483jpl_type_void(void) -->
 1484    "V".
 jCallBooleanMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rbool:boolean)
 1490jCallBooleanMethod(Obj, MethodID, Types, Params, Rbool) :-
 1491    jni_params_put(Params, Types, ParamBuf),
 1492    jni_func(39, Obj, MethodID, ParamBuf, Rbool).
 jCallByteMethod(+Obj:jref, +MethodID:methodId, +Types, +Params:list(datum), -Rbyte:byte)
 1498jCallByteMethod(Obj, MethodID, Types, Params, Rbyte) :-
 1499    jni_params_put(Params, Types, ParamBuf),
 1500    jni_func(42, Obj, MethodID, ParamBuf, Rbyte).
 jCallCharMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rchar:char)
 1506jCallCharMethod(Obj, MethodID, Types, Params, Rchar) :-
 1507    jni_params_put(Params, Types, ParamBuf),
 1508    jni_func(45, Obj, MethodID, ParamBuf, Rchar).
 jCallDoubleMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rdouble:double)
 1513jCallDoubleMethod(Obj, MethodID, Types, Params, Rdouble) :-
 1514    jni_params_put(Params, Types, ParamBuf),
 1515    jni_func(60, Obj, MethodID, ParamBuf, Rdouble).
 jCallFloatMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rfloat:float)
 1520jCallFloatMethod(Obj, MethodID, Types, Params, Rfloat) :-
 1521    jni_params_put(Params, Types, ParamBuf),
 1522    jni_func(57, Obj, MethodID, ParamBuf, Rfloat).
 jCallIntMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rint:int)
 1527jCallIntMethod(Obj, MethodID, Types, Params, Rint) :-
 1528    jni_params_put(Params, Types, ParamBuf),
 1529    jni_func(51, Obj, MethodID, ParamBuf, Rint).
 jCallLongMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rlong:long)
 1534jCallLongMethod(Obj, MethodID, Types, Params, Rlong) :-
 1535    jni_params_put(Params, Types, ParamBuf),
 1536    jni_func(54, Obj, MethodID, ParamBuf, Rlong).
 jCallObjectMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Robj:jref)
 1541jCallObjectMethod(Obj, MethodID, Types, Params, Robj) :-
 1542    jni_params_put(Params, Types, ParamBuf),
 1543    jni_func(36, Obj, MethodID, ParamBuf, Robj).
 jCallShortMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rshort:short)
 1548jCallShortMethod(Obj, MethodID, Types, Params, Rshort) :-
 1549    jni_params_put(Params, Types, ParamBuf),
 1550    jni_func(48, Obj, MethodID, ParamBuf, Rshort).
 jCallStaticBooleanMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rbool:boolean)
 1555jCallStaticBooleanMethod(Class, MethodID, Types, Params, Rbool) :-
 1556    jni_params_put(Params, Types, ParamBuf),
 1557    jni_func(119, Class, MethodID, ParamBuf, Rbool).
 jCallStaticByteMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rbyte:byte)
 1562jCallStaticByteMethod(Class, MethodID, Types, Params, Rbyte) :-
 1563    jni_params_put(Params, Types, ParamBuf),
 1564    jni_func(122, Class, MethodID, ParamBuf, Rbyte).
 jCallStaticCharMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rchar:char)
 1569jCallStaticCharMethod(Class, MethodID, Types, Params, Rchar) :-
 1570    jni_params_put(Params, Types, ParamBuf),
 1571    jni_func(125, Class, MethodID, ParamBuf, Rchar).
 jCallStaticDoubleMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rdouble:double)
 1576jCallStaticDoubleMethod(Class, MethodID, Types, Params, Rdouble) :-
 1577    jni_params_put(Params, Types, ParamBuf),
 1578    jni_func(140, Class, MethodID, ParamBuf, Rdouble).
 jCallStaticFloatMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rfloat:float)
 1583jCallStaticFloatMethod(Class, MethodID, Types, Params, Rfloat) :-
 1584    jni_params_put(Params, Types, ParamBuf),
 1585    jni_func(137, Class, MethodID, ParamBuf, Rfloat).
 jCallStaticIntMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rint:int)
 1590jCallStaticIntMethod(Class, MethodID, Types, Params, Rint) :-
 1591    jni_params_put(Params, Types, ParamBuf),
 1592    jni_func(131, Class, MethodID, ParamBuf, Rint).
 jCallStaticLongMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rlong:long)
 1597jCallStaticLongMethod(Class, MethodID, Types, Params, Rlong) :-
 1598    jni_params_put(Params, Types, ParamBuf),
 1599    jni_func(134, Class, MethodID, ParamBuf, Rlong).
 jCallStaticObjectMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Robj:jref)
 1604jCallStaticObjectMethod(Class, MethodID, Types, Params, Robj) :-
 1605    jni_params_put(Params, Types, ParamBuf),
 1606    jni_func(116, Class, MethodID, ParamBuf, Robj).
 jCallStaticShortMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rshort:short)
 1611jCallStaticShortMethod(Class, MethodID, Types, Params, Rshort) :-
 1612    jni_params_put(Params, Types, ParamBuf),
 1613    jni_func(128, Class, MethodID, ParamBuf, Rshort).
 jCallStaticVoidMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum))
 1618jCallStaticVoidMethod(Class, MethodID, Types, Params) :-
 1619    jni_params_put(Params, Types, ParamBuf),
 1620    jni_void(143, Class, MethodID, ParamBuf).
 jCallVoidMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum))
 1625jCallVoidMethod(Obj, MethodID, Types, Params) :-
 1626    jni_params_put(Params, Types, ParamBuf),
 1627    jni_void(63, Obj, MethodID, ParamBuf).
 jFindClass(+ClassName:findclassname, -Class:jref)
 1632jFindClass(ClassName, Class) :-
 1633    jni_func(6, ClassName, Class).
 jGetArrayLength(+Array:jref, -Size:int)
 1638jGetArrayLength(Array, Size) :-
 1639    jni_func(171, Array, Size).
 jGetBooleanArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:boolean_buf)
 1644jGetBooleanArrayRegion(Array, Start, Len, Buf) :-
 1645    jni_void(199, Array, Start, Len, Buf).
 jGetBooleanField(+Obj:jref, +FieldID:fieldId, -Rbool:boolean)
 1650jGetBooleanField(Obj, FieldID, Rbool) :-
 1651    jni_func(96, Obj, FieldID, Rbool).
 jGetByteArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:byte_buf)
 1656jGetByteArrayRegion(Array, Start, Len, Buf) :-
 1657    jni_void(200, Array, Start, Len, Buf).
 jGetByteField(+Obj:jref, +FieldID:fieldId, -Rbyte:byte)
 1662jGetByteField(Obj, FieldID, Rbyte) :-
 1663    jni_func(97, Obj, FieldID, Rbyte).
 jGetCharArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:char_buf)
 1668jGetCharArrayRegion(Array, Start, Len, Buf) :-
 1669    jni_void(201, Array, Start, Len, Buf).
 jGetCharField(+Obj:jref, +FieldID:fieldId, -Rchar:char)
 1674jGetCharField(Obj, FieldID, Rchar) :-
 1675    jni_func(98, Obj, FieldID, Rchar).
 jGetDoubleArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:double_buf)
 1680jGetDoubleArrayRegion(Array, Start, Len, Buf) :-
 1681    jni_void(206, Array, Start, Len, Buf).
 jGetDoubleField(+Obj:jref, +FieldID:fieldId, -Rdouble:double)
 1686jGetDoubleField(Obj, FieldID, Rdouble) :-
 1687    jni_func(103, Obj, FieldID, Rdouble).
 jGetFieldID(+Class:jref, +Name:fieldName, +Type:type, -FieldID:fieldId)
 1692jGetFieldID(Class, Name, Type, FieldID) :-
 1693    jpl_type_to_descriptor(Type, TD),
 1694    jni_func(94, Class, Name, TD, FieldID).
 jGetFloatArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:float_buf)
 1699jGetFloatArrayRegion(Array, Start, Len, Buf) :-
 1700    jni_void(205, Array, Start, Len, Buf).
 jGetFloatField(+Obj:jref, +FieldID:fieldId, -Rfloat:float)
 1705jGetFloatField(Obj, FieldID, Rfloat) :-
 1706    jni_func(102, Obj, FieldID, Rfloat).
 jGetIntArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:int_buf)
 1711jGetIntArrayRegion(Array, Start, Len, Buf) :-
 1712    jni_void(203, Array, Start, Len, Buf).
 jGetIntField(+Obj:jref, +FieldID:fieldId, -Rint:int)
 1717jGetIntField(Obj, FieldID, Rint) :-
 1718    jni_func(100, Obj, FieldID, Rint).
 jGetLongArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:long_buf)
 1723jGetLongArrayRegion(Array, Start, Len, Buf) :-
 1724    jni_void(204, Array, Start, Len, Buf).
 jGetLongField(+Obj:jref, +FieldID:fieldId, -Rlong:long)
 1729jGetLongField(Obj, FieldID, Rlong) :-
 1730    jni_func(101, Obj, FieldID, Rlong).
 jGetMethodID(+Class:jref, +Name:atom, +Type:type, -MethodID:methodId)
 1735jGetMethodID(Class, Name, Type, MethodID) :-
 1736    jpl_type_to_descriptor(Type, TD),
 1737    jni_func(33, Class, Name, TD, MethodID).
 jGetObjectArrayElement(+Array:jref, +Index:int, -Obj:jref)
 1742jGetObjectArrayElement(Array, Index, Obj) :-
 1743    jni_func(173, Array, Index, Obj).
 jGetObjectClass(+Object:jref, -Class:jref)
 1748jGetObjectClass(Object, Class) :-
 1749    jni_func(31, Object, Class).
 jGetObjectField(+Obj:jref, +FieldID:fieldId, -RObj:jref)
 1754jGetObjectField(Obj, FieldID, Robj) :-
 1755    jni_func(95, Obj, FieldID, Robj).
 jGetShortArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:short_buf)
 1760jGetShortArrayRegion(Array, Start, Len, Buf) :-
 1761    jni_void(202, Array, Start, Len, Buf).
 jGetShortField(+Obj:jref, +FieldID:fieldId, -Rshort:short)
 1766jGetShortField(Obj, FieldID, Rshort) :-
 1767    jni_func(99, Obj, FieldID, Rshort).
 jGetStaticBooleanField(+Class:jref, +FieldID:fieldId, -Rbool:boolean)
 1772jGetStaticBooleanField(Class, FieldID, Rbool) :-
 1773    jni_func(146, Class, FieldID, Rbool).
 jGetStaticByteField(+Class:jref, +FieldID:fieldId, -Rbyte:byte)
 1778jGetStaticByteField(Class, FieldID, Rbyte) :-
 1779    jni_func(147, Class, FieldID, Rbyte).
 jGetStaticCharField(+Class:jref, +FieldID:fieldId, -Rchar:char)
 1784jGetStaticCharField(Class, FieldID, Rchar) :-
 1785    jni_func(148, Class, FieldID, Rchar).
 jGetStaticDoubleField(+Class:jref, +FieldID:fieldId, -Rdouble:double)
 1790jGetStaticDoubleField(Class, FieldID, Rdouble) :-
 1791    jni_func(153, Class, FieldID, Rdouble).
 jGetStaticFieldID(+Class:jref, +Name:fieldName, +Type:type, -FieldID:fieldId)
 1796jGetStaticFieldID(Class, Name, Type, FieldID) :-
 1797    jpl_type_to_descriptor(Type, TD),               % cache this?
 1798    jni_func(144, Class, Name, TD, FieldID).
 jGetStaticFloatField(+Class:jref, +FieldID:fieldId, -Rfloat:float)
 1803jGetStaticFloatField(Class, FieldID, Rfloat) :-
 1804    jni_func(152, Class, FieldID, Rfloat).
 jGetStaticIntField(+Class:jref, +FieldID:fieldId, -Rint:int)
 1809jGetStaticIntField(Class, FieldID, Rint) :-
 1810    jni_func(150, Class, FieldID, Rint).
 jGetStaticLongField(+Class:jref, +FieldID:fieldId, -Rlong:long)
 1815jGetStaticLongField(Class, FieldID, Rlong) :-
 1816    jni_func(151, Class, FieldID, Rlong).
 jGetStaticMethodID(+Class:jref, +Name:methodName, +Type:type, -MethodID:methodId)
 1821jGetStaticMethodID(Class, Name, Type, MethodID) :-
 1822    jpl_type_to_descriptor(Type, TD),
 1823    jni_func(113, Class, Name, TD, MethodID).
 jGetStaticObjectField(+Class:jref, +FieldID:fieldId, -RObj:jref)
 1828jGetStaticObjectField(Class, FieldID, Robj) :-
 1829    jni_func(145, Class, FieldID, Robj).
 jGetStaticShortField(+Class:jref, +FieldID:fieldId, -Rshort:short)
 1834jGetStaticShortField(Class, FieldID, Rshort) :-
 1835    jni_func(149, Class, FieldID, Rshort).
 jGetSuperclass(+Class1:jref, -Class2:jref)
 1840jGetSuperclass(Class1, Class2) :-
 1841    jni_func(10, Class1, Class2).
 jIsAssignableFrom(+Class1:jref, +Class2:jref)
 1846jIsAssignableFrom(Class1, Class2) :-
 1847    jni_func(11, Class1, Class2, @(true)).
 jNewBooleanArray(+Length:int, -Array:jref)
 1852jNewBooleanArray(Length, Array) :-
 1853    jni_func(175, Length, Array).
 jNewByteArray(+Length:int, -Array:jref)
 1858jNewByteArray(Length, Array) :-
 1859    jni_func(176, Length, Array).
 jNewCharArray(+Length:int, -Array:jref)
 1864jNewCharArray(Length, Array) :-
 1865    jni_func(177, Length, Array).
 jNewDoubleArray(+Length:int, -Array:jref)
 1870jNewDoubleArray(Length, Array) :-
 1871    jni_func(182, Length, Array).
 jNewFloatArray(+Length:int, -Array:jref)
 1876jNewFloatArray(Length, Array) :-
 1877    jni_func(181, Length, Array).
 jNewIntArray(+Length:int, -Array:jref)
 1882jNewIntArray(Length, Array) :-
 1883    jni_func(179, Length, Array).
 jNewLongArray(+Length:int, -Array:jref)
 1888jNewLongArray(Length, Array) :-
 1889    jni_func(180, Length, Array).
 jNewObject(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Obj:jref)
 1894jNewObject(Class, MethodID, Types, Params, Obj) :-
 1895    jni_params_put(Params, Types, ParamBuf),
 1896    jni_func(30, Class, MethodID, ParamBuf, Obj).
 jNewObjectArray(+Len:int, +Class:jref, +InitVal:jref, -Array:jref)
 1901jNewObjectArray(Len, Class, InitVal, Array) :-
 1902    jni_func(172, Len, Class, InitVal, Array).
 jNewShortArray(+Length:int, -Array:jref)
 1907jNewShortArray(Length, Array) :-
 1908    jni_func(178, Length, Array).
 jSetBooleanArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:boolean_buf)
 1913jSetBooleanArrayRegion(Array, Start, Len, Buf) :-
 1914    jni_void(207, Array, Start, Len, Buf).
 jSetBooleanField(+Obj:jref, +FieldID:fieldId, +Rbool:boolean)
 1919jSetBooleanField(Obj, FieldID, Rbool) :-
 1920    jni_void(105, Obj, FieldID, Rbool).
 jSetByteArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:byte_buf)
 1925jSetByteArrayRegion(Array, Start, Len, Buf) :-
 1926    jni_void(208, Array, Start, Len, Buf).
 jSetByteField(+Obj:jref, +FieldID:fieldId, +Rbyte:byte)
 1931jSetByteField(Obj, FieldID, Rbyte) :-
 1932    jni_void(106, Obj, FieldID, Rbyte).
 jSetCharArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:char_buf)
 1937jSetCharArrayRegion(Array, Start, Len, Buf) :-
 1938    jni_void(209, Array, Start, Len, Buf).
 jSetCharField(+Obj:jref, +FieldID:fieldId, +Rchar:char)
 1943jSetCharField(Obj, FieldID, Rchar) :-
 1944    jni_void(107, Obj, FieldID, Rchar).
 jSetDoubleArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:double_buf)
 1949jSetDoubleArrayRegion(Array, Start, Len, Buf) :-
 1950    jni_void(214, Array, Start, Len, Buf).
 jSetDoubleField(+Obj:jref, +FieldID:fieldId, +Rdouble:double)
 1955jSetDoubleField(Obj, FieldID, Rdouble) :-
 1956    jni_void(112, Obj, FieldID, Rdouble).
 jSetFloatArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:float_buf)
 1961jSetFloatArrayRegion(Array, Start, Len, Buf) :-
 1962    jni_void(213, Array, Start, Len, Buf).
 jSetFloatField(+Obj:jref, +FieldID:fieldId, +Rfloat:float)
 1967jSetFloatField(Obj, FieldID, Rfloat) :-
 1968    jni_void(111, Obj, FieldID, Rfloat).
 jSetIntArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:int_buf)
 1973jSetIntArrayRegion(Array, Start, Len, Buf) :-
 1974    jni_void(211, Array, Start, Len, Buf).
 jSetIntField(+Obj:jref, +FieldID:fieldId, +Rint:int)
 1979jSetIntField(Obj, FieldID, Rint) :-
 1980    jni_void(109, Obj, FieldID, Rint).
 jSetLongArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:long_buf)
 1985jSetLongArrayRegion(Array, Start, Len, Buf) :-
 1986    jni_void(212, Array, Start, Len, Buf).
 jSetLongField(+Obj:jref, +FieldID:fieldId, +Rlong:long)
 1991jSetLongField(Obj, FieldID, Rlong) :-
 1992    jni_void(110, Obj, FieldID, Rlong).
 jSetObjectArrayElement(+Array:jref, +Index:int, +Obj:jref)
 1997jSetObjectArrayElement(Array, Index, Obj) :-
 1998    jni_void(174, Array, Index, Obj).
 jSetObjectField(+Obj:jref, +FieldID:fieldId, +RObj:jref)
 2003jSetObjectField(Obj, FieldID, Robj) :-
 2004    jni_void(104, Obj, FieldID, Robj).
 jSetShortArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:short_buf)
 2009jSetShortArrayRegion(Array, Start, Len, Buf) :-
 2010    jni_void(210, Array, Start, Len, Buf).
 jSetShortField(+Obj:jref, +FieldID:fieldId, +Rshort:short)
 2015jSetShortField(Obj, FieldID, Rshort) :-
 2016    jni_void(108, Obj, FieldID, Rshort).
 jSetStaticBooleanField(+Class:jref, +FieldID:fieldId, +Rbool:boolean)
 2021jSetStaticBooleanField(Class, FieldID, Rbool) :-
 2022    jni_void(155, Class, FieldID, Rbool).
 jSetStaticByteField(+Class:jref, +FieldID:fieldId, +Rbyte:byte)
 2027jSetStaticByteField(Class, FieldID, Rbyte) :-
 2028    jni_void(156, Class, FieldID, Rbyte).
 jSetStaticCharField(+Class:jref, +FieldID:fieldId, +Rchar:char)
 2033jSetStaticCharField(Class, FieldID, Rchar) :-
 2034    jni_void(157, Class, FieldID, Rchar).
 jSetStaticDoubleField(+Class:jref, +FieldID:fieldId, +Rdouble:double)
 2039jSetStaticDoubleField(Class, FieldID, Rdouble) :-
 2040    jni_void(162, Class, FieldID, Rdouble).
 jSetStaticFloatField(+Class:jref, +FieldID:fieldId, +Rfloat:float)
 2045jSetStaticFloatField(Class, FieldID, Rfloat) :-
 2046    jni_void(161, Class, FieldID, Rfloat).
 jSetStaticIntField(+Class:jref, +FieldID:fieldId, +Rint:int)
 2051jSetStaticIntField(Class, FieldID, Rint) :-
 2052    jni_void(159, Class, FieldID, Rint).
 jSetStaticLongField(+Class:jref, +FieldID:fieldId, +Rlong)
 2057jSetStaticLongField(Class, FieldID, Rlong) :-
 2058    jni_void(160, Class, FieldID, Rlong).
 jSetStaticObjectField(+Class:jref, +FieldID:fieldId, +Robj:jref)
 2063jSetStaticObjectField(Class, FieldID, Robj) :-
 2064    jni_void(154, Class, FieldID, Robj).
 jSetStaticShortField(+Class:jref, +FieldID:fieldId, +Rshort:short)
 2069jSetStaticShortField(Class, FieldID, Rshort) :-
 2070    jni_void(158, Class, FieldID, Rshort).
 jni_params_put(+Params:list(datum), +Types:list(type), -ParamBuf:paramBuf)
The old form used a static buffer, hence was not re-entrant; the new form allocates a buffer of one jvalue per arg, puts the (converted) args into respective elements, then returns it (the caller is responsible for freeing it).
 2080jni_params_put(As, Ts, ParamBuf)     :-
 2081    jni_ensure_jvm,                     % in case e.g. NewStringUTF() is called
 2082    length(As, N),
 2083    jni_type_to_xput_code(jvalue, Xc), % Xc will be 15
 2084    jni_alloc_buffer(Xc, N, ParamBuf),
 2085    jni_params_put_1(As, 0, Ts, ParamBuf).
 jni_params_put_1(+Params:list(datum), +N:integer, +JPLTypes:list(type), +ParamBuf:paramBuf)
Params is a (full or partial) list of args-not-yet-stashed.

Types are their (JPL) types (e.g. 'boolean').

N is the arg and buffer index (0+) at which the head of Params is to be stashed.

The old form used a static buffer and hence was non-reentrant; the new form uses a dynamically allocated buffer (which oughta be freed after use).

NB if the (user-provided) actual params were to be unsuitable for conversion to the method-required types, this would fail silently (without freeing the buffer); it's not clear whether the overloaded-method-resolution ensures that all args are convertible

 2104jni_params_put_1([], _, [], _).
 2105jni_params_put_1([A|As], N, [Tjni|Ts], ParamBuf) :-     % type checking?
 2106    (   jni_type_to_xput_code(Tjni, Xc)
 2107    ->  (   A = {Term}                                  % a quoted general term?
 2108        ->  jni_term_to_jref(Term, Ax)                  % convert it to a @(Tag) ref to a new Term instance
 2109        ;   A = Ax
 2110        ),
 2111        jni_param_put(N, Xc, Ax, ParamBuf)              % foreign
 2112    ;   fail                                            % oughta raise an exception?
 2113    ),
 2114    N2 is N+1,
 2115    jni_params_put_1(As, N2, Ts, ParamBuf).             % stash remaining params (if any)
 jni_type_to_xput_code(+JspType, -JniXputCode)
NB JniXputCode determines widening and casting in foreign code

NB the codes could be compiled into jni_method_spec_cache etc. instead of, or as well as, types (for - small - efficiency gain)

 2125jni_type_to_xput_code(boolean,      1).     % JNI_XPUT_BOOLEAN
 2126jni_type_to_xput_code(byte,         2).     % JNI_XPUT_BYTE
 2127jni_type_to_xput_code(char,         3).     % JNI_XPUT_CHAR
 2128jni_type_to_xput_code(short,        4).     % JNI_XPUT_SHORT
 2129jni_type_to_xput_code(int,          5).     % JNI_XPUT_INT
 2130jni_type_to_xput_code(long,         6).     % JNI_XPUT_LONG
 2131jni_type_to_xput_code(float,        7).     % JNI_XPUT_FLOAT
 2132jni_type_to_xput_code(double,       8).     % JNI_XPUT_DOUBLE
 2133jni_type_to_xput_code(class(_,_),   12).    % JNI_XPUT_REF
 2134jni_type_to_xput_code(array(_),     12).    % JNI_XPUT_REF
 2135jni_type_to_xput_code(jvalue,       15).    % JNI_XPUT_JVALUE
 jpl_class_to_constructor_array(+Class:jref, -MethodArray:jref)
NB might this be done more efficiently in foreign code? or in Java?
 2142jpl_class_to_constructor_array(Cx, Ma) :-
 2143    jpl_classname_to_class('java.lang.Class', CC),      % cacheable?
 2144    jGetMethodID( CC, getConstructors, method([],array(class([java,lang,reflect],['Constructor']))), MID), % cacheable?
 2145    jCallObjectMethod(Cx, MID, [], [], Ma).
 jpl_class_to_constructors(+Class:jref, -Methods:list(jref))
 2150jpl_class_to_constructors(Cx, Ms) :-
 2151    jpl_class_to_constructor_array(Cx, Ma),
 2152    jpl_object_array_to_list(Ma, Ms).
 jpl_class_to_field_array(+Class:jref, -FieldArray:jref)
 2157jpl_class_to_field_array(Cx, Fa) :-
 2158    jpl_classname_to_class('java.lang.Class', CC),      % cacheable?
 2159    jGetMethodID(CC, getFields, method([],array(class([java,lang,reflect],['Field']))), MID),  % cacheable?
 2160    jCallObjectMethod(Cx, MID, [], [], Fa).
 jpl_class_to_fields(+Class:jref, -Fields:list(jref))
NB do this in Java (ditto for methods)?
 2167jpl_class_to_fields(C, Fs) :-
 2168    jpl_class_to_field_array(C, Fa),
 2169    jpl_object_array_to_list(Fa, Fs).
 jpl_class_to_method_array(+Class:jref, -MethodArray:jref)
NB migrate into foreign code for efficiency?
 2176jpl_class_to_method_array(Cx, Ma) :-
 2177    jpl_classname_to_class('java.lang.Class', CC),      % cacheable?
 2178    jGetMethodID(CC, getMethods, method([],array(class([java,lang,reflect],['Method']))), MID),  % cacheable?
 2179    jCallObjectMethod(Cx, MID, [], [], Ma).
 jpl_class_to_methods(+Class:jref, -Methods:list(jref))
NB also used for constructors.

NB do this in Java (ditto for fields)?

 2188jpl_class_to_methods(Cx, Ms) :-
 2189    jpl_class_to_method_array(Cx, Ma),
 2190    jpl_object_array_to_list(Ma, Ms).
 jpl_constructor_to_modifiers(+Method, -Modifiers)
NB migrate into foreign code for efficiency?
 2197jpl_constructor_to_modifiers(X, Ms) :-
 2198    jpl_classname_to_class('java.lang.reflect.Constructor', Cx),   % cached?
 2199    jpl_method_to_modifiers_1(X, Cx, Ms).
 jpl_constructor_to_name(+Method:jref, -Name:atom)
It is a JNI convention that each constructor behaves (at least, for reflection), as a method whose name is '<init>'.
 2207jpl_constructor_to_name(_X, '<init>').
 jpl_constructor_to_parameter_types(+Method:jref, -ParameterTypes:list(type))
NB migrate to foreign code for efficiency?
 2214jpl_constructor_to_parameter_types(X, Tfps) :-
 2215    jpl_classname_to_class('java.lang.reflect.Constructor', Cx),   % cached?
 2216    jpl_method_to_parameter_types_1(X, Cx, Tfps).
 jpl_constructor_to_return_type(+Method:jref, -Type:type)
It is a JNI convention that, for the purposes of retrieving a MethodID, a constructor has a return type of 'void'.
 2224jpl_constructor_to_return_type(_X, void).
 jpl_field_spec(+Type:type, -Index:integer, -Name:atom, -Modifiers, -MID:mId, -FieldType:type)
I'm unsure whether arrays have fields, but if they do, this will handle them correctly.
 2231jpl_field_spec(T, I, N, Mods, MID, Tf) :-
 2232    (   jpl_field_spec_is_cached(T)
 2233    ->  jpl_field_spec_cache(T, I, N, Mods, MID, Tf)
 2234    ;   jpl_type_to_class(T, C),
 2235        jpl_class_to_fields(C, Fs),
 2236        (   T = array(_BaseType)    % regardless of base type...
 2237        ->  Tci = array(_)          % ...the "cache index" type is this
 2238        ;   Tci = T
 2239        ),
 2240        jpl_field_spec_1(C, Tci, Fs),
 2241        jpl_assert(jpl_field_spec_is_cached(Tci)),
 2242        jpl_field_spec_cache(Tci, I, N, Mods, MID, Tf)
 2243    ).
 2244
 2245
 2246jpl_field_spec_1(C, Tci, Fs) :-
 2247    (   nth1(I, Fs, F),
 2248        jpl_field_to_name(F, N),
 2249        jpl_field_to_modifiers(F, Mods),
 2250        jpl_field_to_type(F, Tf),
 2251        (   member(static, Mods)
 2252        ->  jGetStaticFieldID(C, N, Tf, MID)
 2253        ;   jGetFieldID(C, N, Tf, MID)
 2254        ),
 2255        jpl_assert(jpl_field_spec_cache(Tci,I,N,Mods,MID,Tf)),
 2256        fail
 2257    ;   true
 2258    ).
 2259
 2260
 2261:- dynamic jpl_field_spec_cache/6.      % document this...
 2262
 2263
 2264:- dynamic jpl_field_spec_is_cached/1.  % document this...
 jpl_field_to_modifiers(+Field:jref, -Modifiers:ordset(modifier))
 2269jpl_field_to_modifiers(F, Ms) :-
 2270    jpl_classname_to_class('java.lang.reflect.Field', Cf),
 2271    jpl_method_to_modifiers_1(F, Cf, Ms).
 jpl_field_to_name(+Field:jref, -Name:atom)
 2276jpl_field_to_name(F, N) :-
 2277    jpl_classname_to_class('java.lang.reflect.Field', Cf),
 2278    jpl_member_to_name_1(F, Cf, N).
 jpl_field_to_type(+Field:jref, -Type:type)
 2283jpl_field_to_type(F, Tf) :-
 2284    jpl_classname_to_class('java.lang.reflect.Field', Cf),
 2285    jGetMethodID(Cf, getType, method([],class([java,lang],['Class'])), MID),
 2286    jCallObjectMethod(F, MID, [], [], Cr),
 2287    jpl_class_to_type(Cr, Tf).
 jpl_method_spec(+Type:type, -Index:integer, -Name:atom, -Arity:integer, -Modifiers:ordset(modifier), -MID:methodId, -ReturnType:type, -ParameterTypes:list(type))
Generates pertinent details of all accessible methods of Type (class/2 or array/1), populating or using the cache as appropriate.
 2295jpl_method_spec(T, I, N, A, Mods, MID, Tr, Tfps) :-
 2296    (   jpl_method_spec_is_cached(T)
 2297    ->  jpl_method_spec_cache(T, I, N, A, Mods, MID, Tr, Tfps)
 2298    ;   jpl_type_to_class(T, C),
 2299        jpl_class_to_constructors(C, Xs),
 2300        jpl_class_to_methods(C, Ms),
 2301        (   T = array(_BaseType)    % regardless of base type...
 2302        ->  Tci = array(_)          % ...the "cache index" type is this
 2303        ;   Tci = T
 2304        ),
 2305        jpl_method_spec_1(C, Tci, Xs, Ms),
 2306        jpl_assert(jpl_method_spec_is_cached(Tci)),
 2307        jpl_method_spec_cache(Tci, I, N, A, Mods, MID, Tr, Tfps)
 2308    ).
 jpl_method_spec_1(+Class:jref, +CacheIndexType:partialType, +Constructors:list(method), +Methods:list(method))
If the original type is e.g. array(byte) then CacheIndexType is array(_) else it is that type.
 2315jpl_method_spec_1(C, Tci, Xs, Ms) :-
 2316    (   (   nth1(I, Xs, X),     % generate constructors, numbered from 1
 2317            jpl_constructor_to_name(X, N),
 2318            jpl_constructor_to_modifiers(X, Mods),
 2319            jpl_constructor_to_return_type(X, Tr),
 2320            jpl_constructor_to_parameter_types(X, Tfps)
 2321        ;   length(Xs, J0),
 2322            nth1(J, Ms, M),     % generate members, continuing numbering
 2323            I is J0+J,
 2324            jpl_method_to_name(M, N),
 2325            jpl_method_to_modifiers(M, Mods),
 2326            jpl_method_to_return_type(M, Tr),
 2327            jpl_method_to_parameter_types(M, Tfps)
 2328        ),
 2329        length(Tfps, A), % arity
 2330        (   member(static, Mods)
 2331        ->  jGetStaticMethodID(C, N, method(Tfps,Tr), MID)
 2332        ;   jGetMethodID(C, N, method(Tfps,Tr), MID)
 2333        ),
 2334        jpl_assert(jpl_method_spec_cache(Tci,I,N,A,Mods,MID,Tr,Tfps)),
 2335        fail
 2336    ;   true
 2337    ).
 2338
 2339
 2340:- dynamic jpl_method_spec_cache/8. 2341
 2342
 2343:- dynamic jpl_method_spec_is_cached/1.
 jpl_method_to_modifiers(+Method:jref, -ModifierSet:ordset(modifier))
 2348jpl_method_to_modifiers(M, Ms) :-
 2349    jpl_classname_to_class('java.lang.reflect.Method', Cm),
 2350    jpl_method_to_modifiers_1(M, Cm, Ms).
 jpl_method_to_modifiers_1(+Method:jref, +ConstructorClass:jref, -ModifierSet:ordset(modifier))
 2355jpl_method_to_modifiers_1(XM, Cxm, Ms) :-
 2356    jGetMethodID(Cxm, getModifiers, method([],int), MID),
 2357    jCallIntMethod(XM, MID, [], [], I),
 2358    jpl_modifier_int_to_modifiers(I, Ms).
 jpl_method_to_name(+Method:jref, -Name:atom)
 2363jpl_method_to_name(M, N) :-
 2364    jpl_classname_to_class('java.lang.reflect.Method', CM),
 2365    jpl_member_to_name_1(M, CM, N).
 jpl_member_to_name_1(+Member:jref, +CM:jref, -Name:atom)
 2370jpl_member_to_name_1(M, CM, N) :-
 2371    jGetMethodID(CM, getName, method([],class([java,lang],['String'])), MID),
 2372    jCallObjectMethod(M, MID, [], [], N).
 jpl_method_to_parameter_types(+Method:jref, -Types:list(type))
 2377jpl_method_to_parameter_types(M, Tfps) :-
 2378    jpl_classname_to_class('java.lang.reflect.Method', Cm),
 2379    jpl_method_to_parameter_types_1(M, Cm, Tfps).
 jpl_method_to_parameter_types_1(+XM:jref, +Cxm:jref, -Tfps:list(type))
XM is (a JPL ref to) an instance of java.lang.reflect.[Constructor|Method]
 2386jpl_method_to_parameter_types_1(XM, Cxm, Tfps) :-
 2387    jGetMethodID(Cxm, getParameterTypes, method([],array(class([java,lang],['Class']))), MID),
 2388    jCallObjectMethod(XM, MID, [], [], Atp),
 2389    jpl_object_array_to_list(Atp, Ctps),
 2390    jpl_classes_to_types(Ctps, Tfps).
 jpl_method_to_return_type(+Method:jref, -Type:type)
 2395jpl_method_to_return_type(M, Tr) :-
 2396    jpl_classname_to_class('java.lang.reflect.Method', Cm),
 2397    jGetMethodID(Cm, getReturnType, method([],class([java,lang],['Class'])), MID),
 2398    jCallObjectMethod(M, MID, [], [], Cr),
 2399    jpl_class_to_type(Cr, Tr).
 2400
 2401
 2402jpl_modifier_bit(public,        0x001).
 2403jpl_modifier_bit(private,       0x002).
 2404jpl_modifier_bit(protected,     0x004).
 2405jpl_modifier_bit(static,        0x008).
 2406jpl_modifier_bit(final,         0x010).
 2407jpl_modifier_bit(synchronized,  0x020).
 2408jpl_modifier_bit(volatile,      0x040).
 2409jpl_modifier_bit(transient,     0x080).
 2410jpl_modifier_bit(native,        0x100).
 2411jpl_modifier_bit(interface,     0x200).
 2412jpl_modifier_bit(abstract,      0x400).
 jpl_modifier_int_to_modifiers(+Int:integer, -ModifierSet:ordset(modifier))
ModifierSet is an ordered (hence canonical) list, possibly empty (although I suspect never in practice?), of modifier atoms, e.g. [public,static]
 2421jpl_modifier_int_to_modifiers(I, Ms) :-
 2422    setof(
 2423        M,                                  %  should use e.g. set_of_all/3
 2424        B^( jpl_modifier_bit(M, B),
 2425            (B /\ I) =\= 0
 2426        ),
 2427        Ms
 2428    ).
 jpl_cache_type_of_ref(+Type:type, +Ref:jref)
Type must be a proper (concrete) JPL type

Ref must be a proper JPL reference (not void)

Type is memoed (if policy so dictates) as the type of the referenced object (unless it's null) by iref (so as not to disable atom-based GC)

NB obsolete lemmas must be watched-out-for and removed

 2442jpl_cache_type_of_ref(T, Ref) :-
 2443    (   jpl_assert_policy(jpl_iref_type_cache(_,_), no)
 2444    ->  true
 2445    ;   \+ ground(T)                            % shouldn't happen (implementation error)
 2446    ->  write('[jpl_cache_type_of_ref/2: arg 1 is not ground]'), nl,    % oughta throw an exception
 2447        fail
 2448    ;   Ref == @(null)                          % a null ref? (this is valid)
 2449    ->  true                                    % silently ignore it
 2450    ;   (   jpl_iref_type_cache(Ref, TC)        % we expect TC == T
 2451        ->  (   T == TC
 2452            ->  true
 2453            ; % write('[JPL: found obsolete tag-type lemma...]'), nl,   % or keep statistics? (why?)
 2454                retractall(jpl_iref_type_cache(Ref,_)),
 2455                jpl_assert(jpl_iref_type_cache(Ref,T))
 2456            )
 2457        ;   jpl_assert(jpl_iref_type_cache(Ref,T))
 2458        )
 2459    ).
 jpl_class_tag_type_cache(-Ref:jref, -ClassType:type)
Ref is a reference to a JVM instance of java.lang.Class which denotes ClassType.

We index on Ref so as to keep these objects around even after an atom garbage collection (if needed once, they are likely to be needed again)

 2470:- dynamic jpl_class_tag_type_cache/2.
 jpl_class_to_ancestor_classes(+Class:jref, -AncestorClasses:list(jref))
AncestorClasses will be a list of (JPL references to) instances of java.lang.Class denoting the "implements" lineage (?), nearest first (the first member denotes the class which Class directly implements, the next (if any) denotes the class which that class implements, and so on to java.lang.Object)
 2481jpl_class_to_ancestor_classes(C, Cas) :-
 2482    (   jpl_class_to_super_class(C, Ca)
 2483    ->  Cas = [Ca|Cas2],
 2484        jpl_class_to_ancestor_classes(Ca, Cas2)
 2485    ;   Cas = []
 2486    ).
 jpl_class_to_classname(+Class:jref, -ClassName:dottedName)
Class is a reference to a class object.

ClassName is its canonical (?) source-syntax (dotted) name, e.g. 'java.util.Date'

NB not used outside jni_junk and jpl_test (is this (still) true?)

NB oughta use the available caches (but their indexing doesn't suit)

 2500jpl_class_to_classname(C, CN) :-
 2501    jpl_call(C, getName, [], CN).
 jpl_class_to_raw_classname(+Class:jref, -ClassName:rawName)
Hhmm, I forget exactly what a "raw" classname is.
 2508jpl_class_to_raw_classname(Cobj, CN) :-
 2509    jpl_classname_to_class('java.lang.Class', CC),      % cached?
 2510    jGetMethodID(CC, getName, method([],class([java,lang],['String'])), MIDgetName),
 2511    jCallObjectMethod(Cobj, MIDgetName, [], [], S),
 2512    S = CN.
 jpl_class_to_raw_classname_chars(+Class:jref, -ClassnameChars:codes)
Class is a reference to a class object

ClassnameChars is a codes representation of its dotted name

 2521jpl_class_to_raw_classname_chars(Cobj, CsCN) :-
 2522    jpl_class_to_raw_classname(Cobj, CN),
 2523    atom_codes(CN, CsCN).
 2524
 2525
 2526jpl_class_to_super_class(C, Cx) :-
 2527    jGetSuperclass(C, Cx),
 2528    Cx \== @(null),         % as returned when C is java.lang.Object, i.e. no superclass
 2529    jpl_cache_type_of_ref(class([java,lang],['Class']), Cx).
 jpl_class_to_type(+ClassObject:jref, -Type:type)
ClassObject is a reference to a class object of Type.

NB should ensure that, if not found in cache, then cache is updated.

Intriguingly, getParameterTypes returns class objects (undocumented AFAIK) with names 'boolean', 'byte' etc. and even 'void' (?!)

 2541jpl_class_to_type(Ref, Type) :-
 2542    (   jpl_class_tag_type_cache(Ref, Tx)
 2543    ->  true
 2544    ;   jpl_class_to_raw_classname_chars(Ref, Cs),   % uncached
 2545        jpl_classname_chars_to_type(Cs, Tr),
 2546        jpl_type_to_canonical_type(Tr, Tx),             % map e.g. class([],[byte]) -> byte
 2547        jpl_assert(jpl_class_tag_type_cache(Ref,Tx))
 2548    ->  true    % the elseif goal should be determinate, but just in case...
 2549    ),
 2550    Type = Tx.
 2551
 2552
 2553jpl_classes_to_types([], []).
 2554jpl_classes_to_types([C|Cs], [T|Ts]) :-
 2555    jpl_class_to_type(C, T),
 2556    jpl_classes_to_types(Cs, Ts).
 2557
 2558
 2559jpl_classname_chars_to_type(Cs, Type) :-
 2560    (   phrase(jpl_type_classname_1(Type), Cs)
 2561    ->  true
 2562    ).
 jpl_classname_to_class(+ClassName:className, -Class:jref)
ClassName unambiguously represents a class, e.g. 'java.lang.String'

Class is a (canonical) reference to the corresponding class object.

NB uses caches where the class is already encountered.

 2573jpl_classname_to_class(N, C) :-
 2574    jpl_classname_to_type(N, T),    % cached
 2575    jpl_type_to_class(T, C).        % cached
 jpl_classname_to_type(+Classname:className, -Type:type)
Classname is any of: a source-syntax (dotted) class name, e.g. 'java.util.Date', '[java.util.Date' or '[L'

Type is its corresponding JPL type structure, e.g. class([java,util],['Date']), array(class([java,util],['Date'])), array(long)

NB by "classname" do I mean "typename"?

NB should this throw an exception for unbound CN? is this public API?

 2588jpl_classname_to_type(CN, T) :-
 2589    (   jpl_classname_type_cache(CN, Tx)
 2590    ->  Tx = T
 2591    ;   atom_codes(CN, CsCN),
 2592        phrase(jpl_type_classname_1(T), CsCN)
 2593    ->  jpl_assert(jpl_classname_type_cache(CN,T)),
 2594        true
 2595    ).
 jpl_classname_type_cache(-Classname:className, -Type:type)
Classname is the atomic name of Type.

NB may denote a class which cannot be found.

 2604:- dynamic jpl_classname_type_cache/2.
 jpl_datum_to_type(+Datum:datum, -Type:type)
Datum must be a JPL representation of an instance of one (or more) Java types;

Type is the unique most specialised type of which Datum denotes an instance;

NB 3 is an instance of byte, char, short, int and long, of which byte and char are the joint, overlapping most specialised types, so this relates 3 to the pseudo subtype 'char_byte';

See also
- jpl_type_to_preferred_concrete_type/2 for converting inferred types to instantiable types
 2619jpl_datum_to_type(D, T) :-
 2620    (   jpl_value_to_type(D, T)
 2621    ->  true
 2622    ;   jpl_ref_to_type(D, T)
 2623    ->  true
 2624    ;   nonvar(D),
 2625        D = {Term}
 2626    ->  (   cyclic_term(Term)
 2627        ->  throw(error(type_error(acyclic,Term),context(jpl_datum_to_type/2,'must be acyclic')))
 2628        ;   atom(Term)
 2629        ->  T = class([org,jpl7],['Atom'])
 2630        ;   integer(Term)
 2631        ->  T = class([org,jpl7],['Integer'])
 2632        ;   float(Term)
 2633        ->  T = class([org,jpl7],['Float'])
 2634        ;   var(Term)
 2635        ->  T = class([org,jpl7],['Variable'])
 2636        ;   T = class([org,jpl7],['Compound'])
 2637        )
 2638    ).
 2639
 2640
 2641jpl_datums_to_most_specific_common_ancestor_type([D], T) :-
 2642    jpl_datum_to_type(D, T).
 2643jpl_datums_to_most_specific_common_ancestor_type([D1,D2|Ds], T0) :-
 2644    jpl_datum_to_type(D1, T1),
 2645    jpl_type_to_ancestor_types(T1, Ts1),
 2646    jpl_datums_to_most_specific_common_ancestor_type_1([D2|Ds], [T1|Ts1], [T0|_]).
 2647
 2648
 2649jpl_datums_to_most_specific_common_ancestor_type_1([], Ts, Ts).
 2650jpl_datums_to_most_specific_common_ancestor_type_1([D|Ds], Ts1, Ts0) :-
 2651    jpl_datum_to_type(D, Tx),
 2652    jpl_lineage_types_type_to_common_lineage_types(Ts1, Tx, Ts2),
 2653    jpl_datums_to_most_specific_common_ancestor_type_1(Ds, Ts2, Ts0).
 jpl_datums_to_types(+Datums:list(datum), -Types:list(type))
Each member of Datums is a JPL value or reference, denoting an instance of some Java type, and the corresponding member of Types denotes the most specialised type of which it is an instance (including some I invented for the overlaps between e.g. char and short).
 2664jpl_datums_to_types([], []).
 2665jpl_datums_to_types([D|Ds], [T|Ts]) :-
 2666    jpl_datum_to_type(D, T),
 2667    jpl_datums_to_types(Ds, Ts).
 jpl_ground_is_type(+X:term)
X, known to be ground, is (or at least superficially resembles :-) a JPL type.
 2674jpl_ground_is_type(X) :-
 2675    jpl_primitive_type(X),
 2676    !.
 2677jpl_ground_is_type(array(X)) :-
 2678    jpl_ground_is_type(X).
 2679jpl_ground_is_type(class(_,_)).
 2680jpl_ground_is_type(method(_,_)).
 2681
 2682
 2683:- dynamic jpl_iref_type_cache/2. 2684
 2685
 2686jpl_lineage_types_type_to_common_lineage_types(Ts, Tx, Ts0) :-
 2687    (   append(_, [Tx|Ts2], Ts)
 2688    ->  [Tx|Ts2] = Ts0
 2689    ;   jpl_type_to_super_type(Tx, Tx2)
 2690    ->  jpl_lineage_types_type_to_common_lineage_types(Ts, Tx2, Ts0)
 2691    ).
 2692
 2693
 2694jpl_non_var_is_object_type(class(_,_)).
 2695
 2696jpl_non_var_is_object_type(array(_)).
 jpl_object_array_to_list(+Array:jref, -Values:list(datum))
Values is a list of JPL values (primitive values or object references) representing the respective elements of Array.
 2704jpl_object_array_to_list(A, Vs) :-
 2705    jpl_array_to_length(A, N),
 2706    jpl_object_array_to_list_1(A, 0, N, Vs).
 jpl_object_array_to_list_1(+A, +I, +N, -Xs)
 2711jpl_object_array_to_list_1(A, I, N, Xs) :-
 2712    (   I == N
 2713    ->  Xs = []
 2714    ;   jGetObjectArrayElement(A, I, X),
 2715        Xs = [X|Xs2],
 2716        J is I+1,
 2717        jpl_object_array_to_list_1(A, J, N, Xs2)
 2718    ).
 jpl_object_to_class(+Object:jref, -Class:jref)
fails silently if Object is not a valid reference to a Java object

Class is a (canonical) reference to the (canonical) class object which represents the class of Object

NB what's the point of caching the type if we don't look there first?

 2730jpl_object_to_class(Obj, C) :-
 2731    jpl_is_object(Obj),
 2732    jGetObjectClass(Obj, C),
 2733    jpl_cache_type_of_ref(class([java,lang],['Class']), C).
 jpl_object_to_type(+Object:jref, -Type:type)
Object must be a proper JPL reference to a Java object (i.e. a class or array instance, but not null, void or String).

Type is the JPL type of that object.

 2743jpl_object_to_type(Ref, Type) :-
 2744    jpl_is_object(Ref),
 2745    (   jpl_iref_type_cache(Ref, T)
 2746    ->  true                                % T is Tag's type
 2747    ;   jpl_object_to_class(Ref, Cobj),     % else get ref to class obj
 2748        jpl_class_to_type(Cobj, T),         % get type of class it denotes
 2749        jpl_assert(jpl_iref_type_cache(Ref,T))
 2750    ),
 2751    Type = T.
 2752
 2753
 2754jpl_object_type_to_super_type(T, Tx) :-
 2755    (   (   T = class(_,_)
 2756        ;   T = array(_)
 2757        )
 2758    ->  jpl_type_to_class(T, C),
 2759        jpl_class_to_super_class(C, Cx),
 2760        Cx \== @(null),
 2761        jpl_class_to_type(Cx, Tx)
 2762    ).
 jpl_primitive_buffer_to_array(+Type, +Xc, +Bp, +I, +Size, -Vcs)
Bp points to a buffer of (sufficient) Type values.

Vcs will be unbound on entry, and on exit will be a list of Size of them, starting at index I (the buffer is indexed from zero)

 2773jpl_primitive_buffer_to_array(T, Xc, Bp, I, Size, [Vc|Vcs]) :-
 2774    jni_fetch_buffer_value(Bp, I, Vc, Xc),
 2775    Ix is I+1,
 2776    (   Ix < Size
 2777    ->  jpl_primitive_buffer_to_array(T, Xc, Bp, Ix, Size, Vcs)
 2778    ;   Vcs = []
 2779    ).
 jpl_primitive_type(-Type:atom) is nondet
Type is an atomic JPL representation of one of Java's primitive types.
?- setof(Type, jpl_primitive_type(Type), Types).
Types = [boolean, byte, char, double, float, int, long, short].
 2791jpl_primitive_type(boolean).
 2792jpl_primitive_type(char).
 2793jpl_primitive_type(byte).
 2794jpl_primitive_type(short).
 2795jpl_primitive_type(int).
 2796jpl_primitive_type(long).
 2797jpl_primitive_type(float).
 2798jpl_primitive_type(double).
 jpl_primitive_type_default_value(-Type:type, -Value:datum)
Each element of any array of (primitive) Type created by jpl_new/3, or any instance of (primitive) Type created by jpl_new/3, will be initialised to Value (to mimic Java semantics).
 2807jpl_primitive_type_default_value(boolean, @(false)).
 2808jpl_primitive_type_default_value(char,    0).
 2809jpl_primitive_type_default_value(byte,    0).
 2810jpl_primitive_type_default_value(short,   0).
 2811jpl_primitive_type_default_value(int,     0).
 2812jpl_primitive_type_default_value(long,    0).
 2813jpl_primitive_type_default_value(float,   0.0).
 2814jpl_primitive_type_default_value(double,  0.0).
 2815
 2816
 2817jpl_primitive_type_super_type(T, Tx) :-
 2818    (   jpl_type_fits_type_direct_prim(T, Tx)
 2819    ;   jpl_type_fits_type_direct_xtra(T, Tx)
 2820    ).
 jpl_primitive_type_term_to_value(+Type, +Term, -Val)
Term, after widening iff appropriate, represents an instance of Type.

Val is the instance of Type which it represents (often the same thing).

NB currently used only by jpl_new_1 when creating an "instance" of a primitive type (which may be misguided completism - you can't do that in Java)

 2833jpl_primitive_type_term_to_value(Type, Term, Val) :-
 2834    (   jpl_primitive_type_term_to_value_1(Type, Term, Val)
 2835    ->  true
 2836    ).
 jpl_primitive_type_term_to_value_1(+Type, +RawValue, -WidenedValue)
I'm not worried about structure duplication here.

NB this oughta be done in foreign code.

 2845jpl_primitive_type_term_to_value_1(boolean, @(false), @(false)).
 2846jpl_primitive_type_term_to_value_1(boolean, @(true), @(true)).
 2847jpl_primitive_type_term_to_value_1(char, I, I) :-
 2848    integer(I),
 2849    I >= 0,
 2850    I =< 65535.         %  (2**16)-1.
 2851jpl_primitive_type_term_to_value_1(byte, I, I) :-
 2852    integer(I),
 2853    I >= 128,           % -(2**7)
 2854    I =< 127.           %  (2**7)-1
 2855jpl_primitive_type_term_to_value_1(short, I, I) :-
 2856    integer(I),
 2857    I >= -32768,        % -(2**15)
 2858    I =<  32767.        %  (2**15)-1
 2859jpl_primitive_type_term_to_value_1(int, I, I) :-
 2860    integer(I),
 2861    I >= -2147483648,   % -(2**31)
 2862    I =<  2147483647.   %  (2**31)-1
 2863jpl_primitive_type_term_to_value_1(long, I, I) :-
 2864    integer(I),
 2865    I >= -9223372036854775808,  % -(2**63)
 2866    I =<  9223372036854775807.  %  (2**63)-1
 2867jpl_primitive_type_term_to_value_1(float, V, F) :-
 2868    (   integer(V)
 2869    ->  F is float(V)
 2870    ;   float(V)
 2871    ->  F = V
 2872    ).
 2873jpl_primitive_type_term_to_value_1(double, V, F) :-
 2874    (   integer(V)
 2875    ->  F is float(V)
 2876    ;   float(V)
 2877    ->  F = V
 2878    ).
 2879
 2880
 2881jpl_primitive_type_to_ancestor_types(T, Ts) :-
 2882    (   jpl_primitive_type_super_type(T, Ta)
 2883    ->  Ts = [Ta|Tas],
 2884        jpl_primitive_type_to_ancestor_types(Ta, Tas)
 2885    ;   Ts = []
 2886    ).
 2887
 2888
 2889jpl_primitive_type_to_super_type(T, Tx) :-
 2890    jpl_primitive_type_super_type(T, Tx).
 jpl_ref_to_type(+Ref:jref, -Type:type)
Ref must be a proper JPL reference (to an object, null or void).

Type is its type.

 2899jpl_ref_to_type(Ref, T) :-
 2900    (   Ref == @(null)
 2901    ->  T = null
 2902    ;   Ref == @(void)
 2903    ->  T = void
 2904    ;   jpl_object_to_type(Ref, T)
 2905    ).
 jpl_tag_to_type(+Tag:tag, -Type:type)
Tag must be an (atomic) object tag.

Type is its type (either from the cache or by reflection). OBSOLETE

 2915jpl_tag_to_type(Tag, Type) :-
 2916    jni_tag_to_iref(Tag, Iref),
 2917    (   jpl_iref_type_cache(Iref, T)
 2918    ->  true                                % T is Tag's type
 2919    ;   jpl_object_to_class(@(Tag), Cobj), % else get ref to class obj
 2920        jpl_class_to_type(Cobj, T),         % get type of class it denotes
 2921        jpl_assert(jpl_iref_type_cache(Iref,T))
 2922    ),
 2923    Type = T.
 jpl_type_fits_type(+TypeX:type, +TypeY:type) is semidet
TypeX and TypeY must each be proper JPL types.

This succeeds iff TypeX is assignable to TypeY.

 2932jpl_type_fits_type(Tx, Ty) :-
 2933    (   jpl_type_fits_type_1(Tx, Ty)
 2934    ->  true
 2935    ).
 jpl_type_fits_type_1(+T1:type, +T2:type)
NB it doesn't matter that this leaves choicepoints; it serves only jpl_type_fits_type/2
 2942jpl_type_fits_type_1(T, T).
 2943jpl_type_fits_type_1(class(Ps1,Cs1), class(Ps2,Cs2)) :-
 2944    jpl_type_to_class(class(Ps1,Cs1), C1),
 2945    jpl_type_to_class(class(Ps2,Cs2), C2),
 2946    jIsAssignableFrom(C1, C2).
 2947jpl_type_fits_type_1(array(T1), class(Ps2,Cs2)) :-
 2948    jpl_type_to_class(array(T1), C1),
 2949    jpl_type_to_class(class(Ps2,Cs2), C2),
 2950    jIsAssignableFrom(C1, C2).
 2951jpl_type_fits_type_1(array(T1), array(T2)) :-
 2952    jpl_type_to_class(array(T1), C1),
 2953    jpl_type_to_class(array(T2), C2),
 2954    jIsAssignableFrom(C1, C2).
 2955jpl_type_fits_type_1(null, class(_,_)).
 2956jpl_type_fits_type_1(null, array(_)).
 2957jpl_type_fits_type_1(T1, T2) :-
 2958    jpl_type_fits_type_xprim(T1, T2).
 2959
 2960
 2961jpl_type_fits_type_direct_prim(float, double).
 2962jpl_type_fits_type_direct_prim(long,  float).
 2963jpl_type_fits_type_direct_prim(int,   long).
 2964jpl_type_fits_type_direct_prim(char,  int).
 2965jpl_type_fits_type_direct_prim(short, int).
 2966jpl_type_fits_type_direct_prim(byte,  short).
 2967
 2968
 2969jpl_type_fits_type_direct_xprim(Tp, Tq) :-
 2970    jpl_type_fits_type_direct_prim(Tp, Tq).
 2971jpl_type_fits_type_direct_xprim(Tp, Tq) :-
 2972    jpl_type_fits_type_direct_xtra(Tp, Tq).
 jpl_type_fits_type_direct_xtra(-PseudoType:type, -ConcreteType:type)
This defines the direct subtype-supertype relationships which involve the intersection pseudo types char_int, char_short and char_byte
 2980jpl_type_fits_type_direct_xtra(char_int,   int).    % char_int is a direct subtype of int
 2981jpl_type_fits_type_direct_xtra(char_int,   char).   % etc.
 2982jpl_type_fits_type_direct_xtra(char_short, short).
 2983jpl_type_fits_type_direct_xtra(char_short, char).
 2984jpl_type_fits_type_direct_xtra(char_byte,  byte).
 2985jpl_type_fits_type_direct_xtra(char_byte,  char).
 2986jpl_type_fits_type_direct_xtra(overlong,   float).  % 6/Oct/2006 experiment
 jpl_type_fits_type_xprim(-Tp, -T) is nondet
NB serves only jpl_type_fits_type_1/2
 2993jpl_type_fits_type_xprim(Tp, T) :-
 2994    jpl_type_fits_type_direct_xprim(Tp, Tq),
 2995    (   Tq = T
 2996    ;   jpl_type_fits_type_xprim(Tq, T)
 2997    ).
 jpl_type_to_ancestor_types(+T:type, -Tas:list(type))
This does not accommodate the assignability of null, but that's OK (?) since "type assignability" and "type ancestry" are not equivalent.
 3005jpl_type_to_ancestor_types(T, Tas) :-
 3006    (   (   T = class(_,_)
 3007        ;   T = array(_)
 3008        )
 3009    ->  jpl_type_to_class(T, C),
 3010        jpl_class_to_ancestor_classes(C, Cas),
 3011        jpl_classes_to_types(Cas, Tas)
 3012    ;   jpl_primitive_type_to_ancestor_types(T, Tas)
 3013    ->  true
 3014    ).
 jpl_type_to_canonical_type(+Type:type, -CanonicalType:type)
Type must be a type, not necessarily canonical.

CanonicalType will be equivalent and canonical.

Example

?- jpl:jpl_type_to_canonical_type(class([],[byte]), T).
T = byte.
 3029jpl_type_to_canonical_type(array(T), array(Tc)) :-
 3030    !,
 3031    jpl_type_to_canonical_type(T, Tc).
 3032jpl_type_to_canonical_type(class([],[void]), void) :-
 3033    !.
 3034jpl_type_to_canonical_type(class([],[N]), N) :-
 3035    jpl_primitive_type(N),
 3036    !.
 3037jpl_type_to_canonical_type(class(Ps,Cs), class(Ps,Cs)) :-
 3038    !.
 3039jpl_type_to_canonical_type(void, void) :-
 3040    !.
 3041jpl_type_to_canonical_type(P, P) :-
 3042    jpl_primitive_type(P).
 jpl_type_to_class(+Type:type, -Class:jref)
Incomplete types are now never cached (or otherwise passed around).

jFindClass throws an exception if FCN can't be found.

 3051jpl_type_to_class(T, RefA) :-
 3052    (   ground(T)
 3053	->  (   jpl_class_tag_type_cache(RefB, T)
 3054	    ->  true
 3055	    ;   (   jpl_type_to_findclassname(T, FCN)   % peculiar syntax for FindClass()
 3056	        ->  jFindClass(FCN, RefB),       % which caches type of RefB
 3057	            jpl_cache_type_of_ref(class([java,lang],['Class']), RefB)    % 9/Nov/2004 bugfix (?)
 3058	        ),
 3059	        jpl_assert(jpl_class_tag_type_cache(RefB,T))
 3060	    ),
 3061	    RefA = RefB
 3062    ;   throw(error(instantiation_error,context(jpl_type_to_class/2,'1st arg must be bound to a JPL type')))
 3063    ).
 jpl_type_to_nicename(+Type:type, -NiceName:dottedName)
Type, which is a class or array type (not sure about the others...), is denoted by ClassName in dotted syntax.

NB is this used? is "nicename" well defined and necessary?

NB this could use caching if indexing were amenable.

Examples

?- jpl:jpl_type_to_nicename(class([java,util],['Date']), Name).
Name = 'java.util.Date'.

?- jpl:jpl_type_to_nicename(boolean, Name).
Name = boolean.
See also
- jpl_type_to_classname/2
 3086jpl_type_to_nicename(T, NN) :-
 3087    (   jpl_primitive_type(T)
 3088    ->  NN = T
 3089    ;   (   phrase(jpl_type_classname_1(T), Cs)
 3090        ->  atom_codes(CNx, Cs),                                % green commit to first solution
 3091            NN = CNx
 3092        )
 3093    ).
 jpl_type_to_classname(+Type:type, -ClassName:dottedName)
Type, which is a class or array type (not sure about the others...), is denoted by ClassName in dotted syntax.

e.g. jpl_type_to_classname(class([java,util],['Date']), 'java.util.Date')

See also
- jpl_type_to_nicename/2
 3105jpl_type_to_classname(T, CN) :-
 3106    (   phrase(jpl_type_classname_1(T), Cs)
 3107    ->  atom_codes(CNx, Cs),                                % green commit to first solution
 3108        CN = CNx
 3109    ).
 jpl_type_to_descriptor(+Type:type, -Descriptor:descriptor)
Type (denoting any Java type) (can also be a JPL method/2 structure (?!)) is represented by Descriptor (JVM internal syntax)

Example

?- jpl:jpl_type_to_descriptor(class([java,util],['Date']), Descriptor).
Descriptor = 'Ljava/util/Date;'.

I'd cache this, but I'd prefer more efficient indexing on types (hashed?)

 3126jpl_type_to_descriptor(T, D) :-
 3127    (   phrase(jpl_type_descriptor_1(T), Cs)
 3128    ->  atom_codes(Dx, Cs),
 3129        D = Dx
 3130    ).
 jpl_type_to_findclassname(+Type:type, -FindClassName:findClassName)
FindClassName denotes Type (class or array only) in the syntax required peculiarly by JNI's FindClass().

Example

?- jpl:jpl_type_to_findclassname(class([java,util],['Date']), FindClassName).
FindClassName = 'java/util/Date'.
 3144jpl_type_to_findclassname(T, FCN) :-
 3145    (   phrase(jpl_type_findclassname(T), Cs)
 3146    ->  atom_codes(FCNx, Cs),
 3147        FCN = FCNx
 3148    ).
 jpl_type_to_super_type(+Type:type, -SuperType:type)
Type should be a proper JPL type.

SuperType is the (at most one) type which it directly implements (if it's a class).

If Type denotes a class, this works only if that class can be found.

 3159jpl_type_to_super_type(T, Tx) :-
 3160    (   jpl_object_type_to_super_type(T, Tx)
 3161    ->  true
 3162    ;   jpl_primitive_type_to_super_type(T, Tx)
 3163    ->  true
 3164    ).
 jpl_type_to_preferred_concrete_type(+Type:type, -ConcreteType:type)
Type must be a canonical JPL type, possibly an inferred pseudo type such as char_int or array(char_byte)

ConcreteType is the preferred concrete (Java-instantiable) type.

Example

?- jpl_type_to_preferred_concrete_type(array(char_byte), T).
T = array(byte).

NB introduced 16/Apr/2005 to fix bug whereby jpl_list_to_array([1,2,3],A) failed because the lists's inferred type of array(char_byte) is not Java-instantiable

 3183jpl_type_to_preferred_concrete_type(T, Tc) :-
 3184    (   jpl_type_to_preferred_concrete_type_1(T, TcX)
 3185    ->  Tc = TcX
 3186    ).
 3187
 3188
 3189jpl_type_to_preferred_concrete_type_1(char_int, int).
 3190jpl_type_to_preferred_concrete_type_1(char_short, short).
 3191jpl_type_to_preferred_concrete_type_1(char_byte, byte).
 3192jpl_type_to_preferred_concrete_type_1(array(T), array(Tc)) :-
 3193    jpl_type_to_preferred_concrete_type_1(T, Tc).
 3194jpl_type_to_preferred_concrete_type_1(T, T).
 jpl_types_fit_type(+Types:list(type), +Type:type)
Each member of Types is (independently) (if that means anything) assignable to Type.

Used in dynamic type check when attempting to e.g. assign list of values to array.

 3203jpl_types_fit_type([], _).
 3204jpl_types_fit_type([T1|T1s], T2) :-
 3205    jpl_type_fits_type(T1, T2),
 3206    jpl_types_fit_type(T1s, T2).
 jpl_types_fit_types(+Types1:list(type), +Types2:list(type))
Each member type of Types1 "fits" the respective member type of Types2.
 3213jpl_types_fit_types([], []).
 3214jpl_types_fit_types([T1|T1s], [T2|T2s]) :-
 3215    jpl_type_fits_type(T1, T2),
 3216    jpl_types_fit_types(T1s, T2s).
 jpl_value_to_type(+Value:datum, -Type:type)
Value must be a proper JPL datum other than a ref i.e. primitive, String or void

Type is its unique most specific type, which may be one of the pseudo types char_byte, char_short or char_int.

 3227jpl_value_to_type(V, T) :-
 3228    ground(V),                          % critically assumed by jpl_value_to_type_1/2
 3229    (   jpl_value_to_type_1(V, Tv)      % 2nd arg must be unbound
 3230    ->  T = Tv
 3231    ).
 jpl_value_to_type_1(+Value:datum, -Type:type) is semidet
Type is the unique most specific JPL type of which Value represents an instance.

Called solely by jpl_value_to_type/2, which commits to first solution.

NB some integer values are of JPL-peculiar uniquely most specific subtypes, i.e. char_byte, char_short, char_int but all are understood by JPL's internal utilities which call this proc.

NB we regard float as subtype of double.

NB objects and refs always have straightforward types.

 3248jpl_value_to_type_1(@(false), boolean) :- !.
 3249jpl_value_to_type_1(@(true), boolean) :- !.
 3250jpl_value_to_type_1(A, class([java,lang],['String'])) :-   % yes it's a "value"
 3251    atom(A),
 3252    !.
 3253jpl_value_to_type_1(I, T) :-
 3254    integer(I),
 3255    !,
 3256    (   I >= 0
 3257    ->  (   I  < 128                 ->  T = char_byte
 3258        ;   I  < 32768               ->  T = char_short
 3259        ;   I  < 65536               ->  T = char_int
 3260        ;   I  < 2147483648          ->  T = int
 3261        ;   I =< 9223372036854775807 ->  T = long
 3262        ;   T = overlong
 3263        )
 3264    ;   I >= -128                 ->  T = byte
 3265    ;   I >= -32768               ->  T = short
 3266    ;   I >= -2147483648          ->  T = int
 3267    ;   I >= -9223372036854775808 ->  T = long
 3268    ;   T = overlong
 3269    ).
 3270jpl_value_to_type_1(F, float) :-
 3271    float(F).
 jpl_is_class(@Term)
True if Term is a JPL reference to an instance of java.lang.Class.
 3278jpl_is_class(X) :-
 3279    jpl_is_object(X),
 3280    jpl_object_to_type(X, class([java,lang],['Class'])).
 jpl_is_false(@Term)
True if Term is @(false), the JPL representation of the Java boolean value 'false'.
 3287jpl_is_false(X) :-
 3288    X == @(false).
 jpl_is_fieldID(-X)
X is a JPL field ID structure (jfieldID/1)..

NB JPL internal use only.

NB applications should not be messing with these.

NB a var arg may get bound.

 3301jpl_is_fieldID(jfieldID(X)) :-
 3302    integer(X).
 jpl_is_methodID(-X)
X is a JPL method ID structure (jmethodID/1).

NB JPL internal use only.

NB applications should not be messing with these.

NB a var arg may get bound.

 3315jpl_is_methodID(jmethodID(X)) :-   % NB a var arg may get bound...
 3316    integer(X).
 jpl_is_null(@Term)
True if Term is @(null), the JPL representation of Java's 'null' reference.
 3323jpl_is_null(X) :-
 3324    X == @(null).
 jpl_is_object(@Term)
True if Term is a well-formed JPL object reference.

NB this checks only syntax, not whether the object exists.

 3333jpl_is_object(X) :-
 3334	blob(X, jref).
 jpl_is_object_type(@Term)
True if Term is an object (class or array) type, not e.g. a primitive, null or void.
 3341jpl_is_object_type(T) :-
 3342    \+ var(T),
 3343    jpl_non_var_is_object_type(T).
 jpl_is_ref(@Term)
True if Term is a well-formed JPL reference, either to a Java object or to Java's notional but important 'null' non-object.
 3352jpl_is_ref(Term) :-
 3353    (	jpl_is_object(Term)
 3354    ->	true
 3355    ;	jpl_is_null(Term)
 3356    ->	true
 3357    ).
 jpl_is_true(@Term)
True if Term is @(true), the JPL representation of the Java boolean value 'true'.
 3365jpl_is_true(X) :-
 3366    X == @(true).
 jpl_is_type(@Term)
True if Term is a well-formed JPL type structure.
 3372jpl_is_type(X) :-
 3373    ground(X),
 3374    jpl_ground_is_type(X).
 jpl_is_void(@Term)
True if Term is @(void), the JPL representation of the pseudo Java value 'void' (which is returned by jpl_call/4 when invoked on void methods).

NB you can try passing 'void' back to Java, but it won't ever be interested.

 3385jpl_is_void(X) :-
 3386    X == @(void).
 jpl_false(-X:datum) is semidet
X is @(false), the JPL representation of the Java boolean value 'false'.
See also
- jpl_is_false/1
 3395jpl_false(@(false)).
 jpl_null(-X:datum) is semidet
X is @(null), the JPL representation of Java's 'null' reference.
See also
- jpl_is_null/1
 3403jpl_null(@(null)).
 jpl_true(-X:datum) is semidet
X is @(true), the JPL representation of the Java boolean value 'true'.
See also
- jpl_is_true/1
 3412jpl_true(@(true)).
 jpl_void(-X:datum) is semidet
X is @(void), the JPL representation of the pseudo Java value 'void'.
See also
- jpl_is_void/1
 3422jpl_void(@(void)).
 jpl_array_to_length(+Array:jref, -Length:integer)
Array should be a JPL reference to a Java array of any type.

Length is the length of that array. This is a utility predicate, defined thus:

jpl_array_to_length(A, N) :-
    (   jpl_ref_to_type(A, array(_))
    ->  jGetArrayLength(A, N)
    ).
 3439jpl_array_to_length(A, N) :-
 3440    (   jpl_ref_to_type(A, array(_))    % can this be done cheaper e.g. in foreign code?
 3441    ->  jGetArrayLength(A, N)           % *must* be array, else undefined (crash?)
 3442    ).
 jpl_array_to_list(+Array:jref, -Elements:list(datum))
Array should be a JPL reference to a Java array of any type.

Elements is a Prolog list of JPL representations of the array's elements (values or references, as appropriate). This is a utility predicate, defined thus:

jpl_array_to_list(A, Es) :-
    jpl_array_to_length(A, Len),
    (   Len > 0
    ->  LoBound is 0,
        HiBound is Len-1,
        jpl_get(A, LoBound-HiBound, Es)
    ;   Es = []
    ).
 3464jpl_array_to_list(A, Es) :-
 3465    jpl_array_to_length(A, Len),
 3466    (   Len > 0
 3467    ->  LoBound is 0,
 3468        HiBound is Len-1,
 3469        jpl_get(A, LoBound-HiBound, Es)
 3470    ;   Es = []
 3471    ).
 jpl_datums_to_array(+Datums:list(datum), -A:jref)
A will be a JPL reference to a new Java array, whose base type is the most specific Java type of which each member of Datums is (directly or indirectly) an instance.

NB this fails silently if

 3486jpl_datums_to_array(Ds, A) :-
 3487    ground(Ds),
 3488    jpl_datums_to_most_specific_common_ancestor_type(Ds, T),    % T may be pseudo e.g. char_byte
 3489    jpl_type_to_preferred_concrete_type(T, Tc),    % bugfix added 16/Apr/2005
 3490    jpl_new(array(Tc), Ds, A).
 jpl_enumeration_element(+Enumeration:jref, -Element:datum)
Generates each Element from Enumeration.
 3501jpl_enumeration_element(En, E) :-
 3502    (   jpl_call(En, hasMoreElements, [], @(true))
 3503    ->  jpl_call(En, nextElement, [], Ex),
 3504        (   E = Ex
 3505        ;   jpl_enumeration_element(En, E)
 3506        )
 3507    ).
 jpl_enumeration_to_list(+Enumeration:jref, -Elements:list(datum))
Enumeration should be a JPL reference to an object which implements the Enumeration interface.

Elements is a Prolog list of JPL references to the enumerated objects. This is a utility predicate, defined thus:

jpl_enumeration_to_list(Enumeration, Es) :-
    (   jpl_call(Enumeration, hasMoreElements, [], @(true))
    ->  jpl_call(Enumeration, nextElement, [], E),
        Es = [E|Es1],
        jpl_enumeration_to_list(Enumeration, Es1)
    ;   Es = []
    ).
 3528jpl_enumeration_to_list(Enumeration, Es) :-
 3529    (   jpl_call(Enumeration, hasMoreElements, [], @(true))
 3530    ->  jpl_call(Enumeration, nextElement, [], E),
 3531        Es = [E|Es1],
 3532        jpl_enumeration_to_list(Enumeration, Es1)
 3533    ;   Es = []
 3534    ).
 jpl_hashtable_pair(+HashTable:jref, -KeyValuePair:pair(datum,datum)) is nondet
Generates Key-Value pairs from the given HashTable.

NB String is converted to atom but Integer is presumably returned as an object ref (i.e. as elsewhere, no auto unboxing);

NB this is anachronistic: the Map interface is preferred.

 3546jpl_hashtable_pair(HT, K-V) :-
 3547    jpl_call(HT, keys, [], Ek),
 3548    jpl_enumeration_to_list(Ek, Ks),
 3549    member(K, Ks),
 3550    jpl_call(HT, get, [K], V).
 jpl_iterator_element(+Iterator:jref, -Element:datum)
Iterator should be a JPL reference to an object which implements the java.util.Iterator interface.

Element is the JPL representation of the next element in the iteration. This is a utility predicate, defined thus:

jpl_iterator_element(I, E) :-
    (   jpl_call(I, hasNext, [], @(true))
    ->  (   jpl_call(I, next, [], E)
        ;   jpl_iterator_element(I, E)
        )
    ).
 3570jpl_iterator_element(I, E) :-
 3571    (   jpl_call(I, hasNext, [], @(true))
 3572    ->  (   jpl_call(I, next, [], E)
 3573        ;   jpl_iterator_element(I, E)
 3574        )
 3575    ).
 jpl_list_to_array(+Datums:list(datum), -Array:jref)
Datums should be a proper Prolog list of JPL datums (values or references).

If Datums have a most specific common supertype, then Array is a JPL reference to a new Java array, whose base type is that common supertype, and whose respective elements are the Java values or objects represented by Datums.

 3588jpl_list_to_array(Ds, A) :-
 3589    jpl_datums_to_array(Ds, A).
 jpl_terms_to_array(+Terms:list(term), -Array:jref) is semidet
Terms should be a proper Prolog list of arbitrary terms.

Array is a JPL reference to a new Java array of org.jpl7.Term, whose elements represent the respective members of the list.

 3599jpl_terms_to_array(Ts, A) :-
 3600    jpl_terms_to_array_1(Ts, Ts2),
 3601    jpl_new(array(class([org,jpl7],['Term'])), Ts2, A).
 3602
 3603
 3604jpl_terms_to_array_1([], []).
 3605jpl_terms_to_array_1([T|Ts], [{T}|Ts2]) :-
 3606    jpl_terms_to_array_1(Ts, Ts2).
 jpl_array_to_terms(+JRef:jref, -Terms:list(term))
JRef should be a JPL reference to a Java array of org.jpl7.Term instances (or ots subtypes); Terms will be a list of the terms which the respective array elements represent.
 3615jpl_array_to_terms(JRef, Terms) :-
 3616    jpl_call('org.jpl7.Util', termArrayToList, [JRef], {Terms}).
 jpl_map_element(+Map:jref, -KeyValue:pair(datum,datum)) is nondet
Map must be a JPL Reference to an object which implements the java.util.Map interface

This generates each Key-Value pair from the Map, e.g.

?- jpl_call('java.lang.System', getProperties, [], Map), jpl_map_element(Map, E).
Map = @<jref>(0x20b5c38),
E = 'java.runtime.name'-'Java(TM) SE Runtime Environment' ;
Map = @<jref>(0x20b5c38),
E = 'sun.boot.library.path'-'C:\\Program Files\\Java\\jre7\\bin'
etc.

This is a utility predicate, defined thus:

jpl_map_element(Map, K-V) :-
    jpl_call(Map, entrySet, [], ES),
    jpl_set_element(ES, E),
    jpl_call(E, getKey, [], K),
    jpl_call(E, getValue, [], V).
 3645jpl_map_element(Map, K-V) :-
 3646    jpl_call(Map, entrySet, [], ES),
 3647    jpl_set_element(ES, E),
 3648    jpl_call(E, getKey, [], K),
 3649    jpl_call(E, getValue, [], V).
 jpl_set_element(+Set:jref, -Element:datum) is nondet
Set must be a JPL reference to an object which implements the java.util.Set interface.

On backtracking, Element is bound to a JPL representation of each element of Set. This is a utility predicate, defined thus:

jpl_set_element(S, E) :-
    jpl_call(S, iterator, [], I),
    jpl_iterator_element(I, E).
 3666jpl_set_element(S, E) :-
 3667    jpl_call(S, iterator, [], I),
 3668    jpl_iterator_element(I, E).
 jpl_servlet_byref(+Config, +Request, +Response)
This serves the byref servlet demo, exemplifying one tactic for implementing a servlet in Prolog by accepting the Request and Response objects as JPL references and accessing their members via JPL as required;
See also
- jpl_servlet_byval/3
 3680jpl_servlet_byref(Config, Request, Response) :-
 3681    jpl_call(Config, getServletContext, [], Context),
 3682    jpl_call(Response, setStatus, [200], _),
 3683    jpl_call(Response, setContentType, ['text/html'], _),
 3684    jpl_call(Response, getWriter, [], W),
 3685    jpl_call(W, println, ['<html><head></head><body><h2>jpl_servlet_byref/3 says:</h2><pre>'], _),
 3686    jpl_call(W, println, ['\nservlet context stuff:'], _),
 3687    jpl_call(Context, getInitParameterNames, [], ContextInitParameterNameEnum),
 3688    jpl_enumeration_to_list(ContextInitParameterNameEnum, ContextInitParameterNames),
 3689    length(ContextInitParameterNames, NContextInitParameterNames),
 3690    atomic_list_concat(['\tContext.InitParameters = ',NContextInitParameterNames], NContextInitParameterNamesMsg),
 3691    jpl_call(W, println, [NContextInitParameterNamesMsg], _),
 3692    (   member(ContextInitParameterName, ContextInitParameterNames),
 3693        jpl_call(Context, getInitParameter, [ContextInitParameterName], ContextInitParameter),
 3694        atomic_list_concat(['\t\tContext.InitParameter[',ContextInitParameterName,'] = ',ContextInitParameter], ContextInitParameterMsg),
 3695        jpl_call(W, println, [ContextInitParameterMsg], _),
 3696        fail
 3697    ;   true
 3698    ),
 3699    jpl_call(Context, getMajorVersion, [], MajorVersion),
 3700    atomic_list_concat(['\tContext.MajorVersion = ',MajorVersion], MajorVersionMsg),
 3701    jpl_call(W, println, [MajorVersionMsg], _),
 3702    jpl_call(Context, getMinorVersion, [], MinorVersion),
 3703    atomic_list_concat(['\tContext.MinorVersion = ',MinorVersion], MinorVersionMsg),
 3704    jpl_call(W, println, [MinorVersionMsg], _),
 3705    jpl_call(Context, getServerInfo, [], ServerInfo),
 3706    atomic_list_concat(['\tContext.ServerInfo = ',ServerInfo], ServerInfoMsg),
 3707    jpl_call(W, println, [ServerInfoMsg], _),
 3708    jpl_call(W, println, ['\nservlet config stuff:'], _),
 3709    jpl_call(Config, getServletName, [], ServletName),
 3710    (   ServletName == @(null)
 3711    ->  ServletNameAtom = null
 3712    ;   ServletNameAtom = ServletName
 3713    ),
 3714    atomic_list_concat(['\tConfig.ServletName = ',ServletNameAtom], ServletNameMsg),
 3715    jpl_call(W, println, [ServletNameMsg], _),
 3716    jpl_call(Config, getInitParameterNames, [], ConfigInitParameterNameEnum),
 3717    jpl_enumeration_to_list(ConfigInitParameterNameEnum, ConfigInitParameterNames),
 3718    length(ConfigInitParameterNames, NConfigInitParameterNames),
 3719    atomic_list_concat(['\tConfig.InitParameters = ',NConfigInitParameterNames], NConfigInitParameterNamesMsg),
 3720    jpl_call(W, println, [NConfigInitParameterNamesMsg], _),
 3721    (   member(ConfigInitParameterName, ConfigInitParameterNames),
 3722        jpl_call(Config, getInitParameter, [ConfigInitParameterName], ConfigInitParameter),
 3723        atomic_list_concat(['\t\tConfig.InitParameter[',ConfigInitParameterName,'] = ',ConfigInitParameter], ConfigInitParameterMsg),
 3724        jpl_call(W, println, [ConfigInitParameterMsg], _),
 3725        fail
 3726    ;   true
 3727    ),
 3728    jpl_call(W, println, ['\nrequest stuff:'], _),
 3729    jpl_call(Request, getAttributeNames, [], AttributeNameEnum),
 3730    jpl_enumeration_to_list(AttributeNameEnum, AttributeNames),
 3731    length(AttributeNames, NAttributeNames),
 3732    atomic_list_concat(['\tRequest.Attributes = ',NAttributeNames], NAttributeNamesMsg),
 3733    jpl_call(W, println, [NAttributeNamesMsg], _),
 3734    (   member(AttributeName, AttributeNames),
 3735        jpl_call(Request, getAttribute, [AttributeName], Attribute),
 3736        jpl_call(Attribute, toString, [], AttributeString),
 3737        atomic_list_concat(['\t\tRequest.Attribute[',AttributeName,'] = ',AttributeString], AttributeMsg),
 3738        jpl_call(W, println, [AttributeMsg], _),
 3739        fail
 3740    ;   true
 3741    ),
 3742    jpl_call(Request, getCharacterEncoding, [], CharacterEncoding),
 3743    (   CharacterEncoding == @(null)
 3744    ->  CharacterEncodingAtom = ''
 3745    ;   CharacterEncodingAtom = CharacterEncoding
 3746    ),
 3747    atomic_list_concat(['\tRequest.CharacterEncoding',' = ',CharacterEncodingAtom], CharacterEncodingMsg),
 3748    jpl_call(W, println, [CharacterEncodingMsg], _),
 3749    jpl_call(Request, getContentLength, [], ContentLength),
 3750    atomic_list_concat(['\tRequest.ContentLength',' = ',ContentLength], ContentLengthMsg),
 3751    jpl_call(W, println, [ContentLengthMsg], _),
 3752    jpl_call(Request, getContentType, [], ContentType),
 3753    (   ContentType == @(null)
 3754    ->  ContentTypeAtom = ''
 3755    ;   ContentTypeAtom = ContentType
 3756    ),
 3757    atomic_list_concat(['\tRequest.ContentType',' = ',ContentTypeAtom], ContentTypeMsg),
 3758    jpl_call(W, println, [ContentTypeMsg], _),
 3759    jpl_call(Request, getParameterNames, [], ParameterNameEnum),
 3760    jpl_enumeration_to_list(ParameterNameEnum, ParameterNames),
 3761    length(ParameterNames, NParameterNames),
 3762    atomic_list_concat(['\tRequest.Parameters = ',NParameterNames], NParameterNamesMsg),
 3763    jpl_call(W, println, [NParameterNamesMsg], _),
 3764    (   member(ParameterName, ParameterNames),
 3765        jpl_call(Request, getParameter, [ParameterName], Parameter),
 3766        atomic_list_concat(['\t\tRequest.Parameter[',ParameterName,'] = ',Parameter], ParameterMsg),
 3767        jpl_call(W, println, [ParameterMsg], _),
 3768        fail
 3769    ;   true
 3770    ),
 3771    jpl_call(Request, getProtocol, [], Protocol),
 3772    atomic_list_concat(['\tRequest.Protocol',' = ',Protocol], ProtocolMsg),
 3773    jpl_call(W, println, [ProtocolMsg], _),
 3774    jpl_call(Request, getRemoteAddr, [], RemoteAddr),
 3775    atomic_list_concat(['\tRequest.RemoteAddr',' = ',RemoteAddr], RemoteAddrMsg),
 3776    jpl_call(W, println, [RemoteAddrMsg], _),
 3777    jpl_call(Request, getRemoteHost, [], RemoteHost),
 3778    atomic_list_concat(['\tRequest.RemoteHost',' = ',RemoteHost], RemoteHostMsg),
 3779    jpl_call(W, println, [RemoteHostMsg], _),
 3780    jpl_call(Request, getScheme, [], Scheme),
 3781    atomic_list_concat(['\tRequest.Scheme',' = ',Scheme], SchemeMsg),
 3782    jpl_call(W, println, [SchemeMsg], _),
 3783    jpl_call(Request, getServerName, [], ServerName),
 3784    atomic_list_concat(['\tRequest.ServerName',' = ',ServerName], ServerNameMsg),
 3785    jpl_call(W, println, [ServerNameMsg], _),
 3786    jpl_call(Request, getServerPort, [], ServerPort),
 3787    atomic_list_concat(['\tRequest.ServerPort',' = ',ServerPort], ServerPortMsg),
 3788    jpl_call(W, println, [ServerPortMsg], _),
 3789    jpl_call(Request, isSecure, [], @(Secure)),
 3790    atomic_list_concat(['\tRequest.Secure',' = ',Secure], SecureMsg),
 3791    jpl_call(W, println, [SecureMsg], _),
 3792    jpl_call(W, println, ['\nHTTP request stuff:'], _),
 3793    jpl_call(Request, getAuthType, [], AuthType),
 3794    (   AuthType == @(null)
 3795    ->  AuthTypeAtom = ''
 3796    ;   AuthTypeAtom = AuthType
 3797    ),
 3798    atomic_list_concat(['\tRequest.AuthType',' = ',AuthTypeAtom], AuthTypeMsg),
 3799    jpl_call(W, println, [AuthTypeMsg], _),
 3800    jpl_call(Request, getContextPath, [], ContextPath),
 3801    (   ContextPath == @(null)
 3802    ->  ContextPathAtom = ''
 3803    ;   ContextPathAtom = ContextPath
 3804    ),
 3805    atomic_list_concat(['\tRequest.ContextPath',' = ',ContextPathAtom], ContextPathMsg),
 3806    jpl_call(W, println, [ContextPathMsg], _),
 3807    jpl_call(Request, getCookies, [], CookieArray),
 3808    (   CookieArray == @(null)
 3809    ->  Cookies = []
 3810    ;   jpl_array_to_list(CookieArray, Cookies)
 3811    ),
 3812    length(Cookies, NCookies),
 3813    atomic_list_concat(['\tRequest.Cookies',' = ',NCookies], NCookiesMsg),
 3814    jpl_call(W, println, [NCookiesMsg], _),
 3815    (   nth0(NCookie, Cookies, Cookie),
 3816        atomic_list_concat(['\t\tRequest.Cookie[',NCookie,']'], CookieMsg),
 3817        jpl_call(W, println, [CookieMsg], _),
 3818        jpl_call(Cookie, getName, [], CookieName),
 3819        atomic_list_concat(['\t\t\tRequest.Cookie.Name = ',CookieName], CookieNameMsg),
 3820        jpl_call(W, println, [CookieNameMsg], _),
 3821        jpl_call(Cookie, getValue, [], CookieValue),
 3822        atomic_list_concat(['\t\t\tRequest.Cookie.Value = ',CookieValue], CookieValueMsg),
 3823        jpl_call(W, println, [CookieValueMsg], _),
 3824        jpl_call(Cookie, getPath, [], CookiePath),
 3825        (   CookiePath == @(null)
 3826        ->  CookiePathAtom = ''
 3827        ;   CookiePathAtom = CookiePath
 3828        ),
 3829        atomic_list_concat(['\t\t\tRequest.Cookie.Path = ',CookiePathAtom], CookiePathMsg),
 3830        jpl_call(W, println, [CookiePathMsg], _),
 3831        jpl_call(Cookie, getComment, [], CookieComment),
 3832        (   CookieComment == @(null)
 3833        ->  CookieCommentAtom = ''
 3834        ;   CookieCommentAtom = CookieComment
 3835        ),
 3836        atomic_list_concat(['\t\t\tRequest.Cookie.Comment = ',CookieCommentAtom], CookieCommentMsg),
 3837        jpl_call(W, println, [CookieCommentMsg], _),
 3838        jpl_call(Cookie, getDomain, [], CookieDomain),
 3839        (   CookieDomain == @(null)
 3840        ->  CookieDomainAtom = ''
 3841        ;   CookieDomainAtom = CookieDomain
 3842        ),
 3843        atomic_list_concat(['\t\t\tRequest.Cookie.Domain = ',CookieDomainAtom], CookieDomainMsg),
 3844        jpl_call(W, println, [CookieDomainMsg], _),
 3845        jpl_call(Cookie, getMaxAge, [], CookieMaxAge),
 3846        atomic_list_concat(['\t\t\tRequest.Cookie.MaxAge = ',CookieMaxAge], CookieMaxAgeMsg),
 3847        jpl_call(W, println, [CookieMaxAgeMsg], _),
 3848        jpl_call(Cookie, getVersion, [], CookieVersion),
 3849        atomic_list_concat(['\t\t\tRequest.Cookie.Version = ',CookieVersion], CookieVersionMsg),
 3850        jpl_call(W, println, [CookieVersionMsg], _),
 3851        jpl_call(Cookie, getSecure, [], @(CookieSecure)),
 3852        atomic_list_concat(['\t\t\tRequest.Cookie.Secure',' = ',CookieSecure], CookieSecureMsg),
 3853        jpl_call(W, println, [CookieSecureMsg], _),
 3854        fail
 3855    ;   true
 3856    ),
 3857    jpl_call(W, println, ['</pre></body></html>'], _),
 3858    true.
 jpl_servlet_byval(+MultiMap, -ContentType:atom, -Body:atom)
This exemplifies an alternative (to jpl_servlet_byref) tactic for implementing a servlet in Prolog; most Request fields are extracted in Java before this is called, and passed in as a multimap (a map, some of whose values are maps).
 3868jpl_servlet_byval(MM, CT, Ba) :-
 3869    CT = 'text/html',
 3870    multimap_to_atom(MM, MMa),
 3871    atomic_list_concat(['<html><head></head><body>','<h2>jpl_servlet_byval/3 says:</h2><pre>', MMa,'</pre></body></html>'], Ba).
 is_pair(?T:term)
I define a half-decent "pair" as having a ground key (any val).
 3878is_pair(Key-_Val) :-
 3879    ground(Key).
 3880
 3881
 3882is_pairs(List) :-
 3883    is_list(List),
 3884    maplist(is_pair, List).
 3885
 3886
 3887multimap_to_atom(KVs, A) :-
 3888    multimap_to_atom_1(KVs, '', Cz, []),
 3889    flatten(Cz, Cs),
 3890    atomic_list_concat(Cs, A).
 3891
 3892
 3893multimap_to_atom_1([], _, Cs, Cs).
 3894multimap_to_atom_1([K-V|KVs], T, Cs1, Cs0) :-
 3895    Cs1 = [T,K,' = '|Cs2],
 3896    (   is_list(V)
 3897    ->  (   is_pairs(V)
 3898        ->  V = V2
 3899        ;   findall(N-Ve, nth1(N, V, Ve), V2)
 3900        ),
 3901        T2 = ['    ',T],
 3902        Cs2 = ['\n'|Cs2a],
 3903        multimap_to_atom_1(V2, T2, Cs2a, Cs3)
 3904    ;   to_atom(V, AV),
 3905        Cs2 = [AV,'\n'|Cs3]
 3906    ),
 3907    multimap_to_atom_1(KVs, T, Cs3, Cs0).
 to_atom(+Term, -Atom)
Unifies Atom with a printed representation of Term.
To be done
- Sort of quoting requirements and use format(codes(Codes),...)
 3916to_atom(Term, Atom) :-
 3917    (   atom(Term)
 3918    ->  Atom = Term                % avoid superfluous quotes
 3919    ;   term_to_atom(Term, Atom)
 3920    ).
 jpl_pl_syntax(-Syntax:atom)
Unifies Syntax with 'traditional' or 'modern' according to the mode in which SWI Prolog 7.x was started
 3927jpl_pl_syntax(Syntax) :-
 3928	(	[] == '[]'
 3929	->	Syntax = traditional
 3930	;	Syntax = modern
 3931	).
 3932
 3933         /*******************************
 3934         *            MESSAGES          *
 3935         *******************************/
 3936
 3937:- multifile
 3938    prolog:error_message/3. 3939
 3940prolog:error_message(java_exception(Ex)) -->
 3941    (   { jpl_call(Ex, toString, [], Msg)
 3942        }
 3943    ->  [ 'Java exception: ~w'-[Msg] ]
 3944    ;   [ 'Java exception: ~w'-[Ex] ]
 3945    ).
 3946
 3947
 3948         /*******************************
 3949         *             PATHS            *
 3950         *******************************/
 3951
 3952:- multifile user:file_search_path/2. 3953:- dynamic   user:file_search_path/2. 3954
 3955user:file_search_path(jar, swi(lib)).
 3956
 3957classpath(DirOrJar) :-
 3958    getenv('CLASSPATH', ClassPath),
 3959    (   current_prolog_flag(windows, true)
 3960    ->  atomic_list_concat(Elems, (;), ClassPath)
 3961    ;   atomic_list_concat(Elems, :, ClassPath)
 3962    ),
 3963    member(DirOrJar, Elems).
 add_search_path(+Var, +Value) is det
Add value to the end of search-path Var. Value is normally a directory. Does not change the environment if Dir is already in Var.
Arguments:
Value- Path to add in OS notation.
 3972add_search_path(Path, Dir) :-
 3973    (   getenv(Path, Old)
 3974    ->  search_path_separator(Sep),
 3975        (   atomic_list_concat(Current, Sep, Old),
 3976            memberchk(Dir, Current)
 3977        ->  true            % already present
 3978        ;   atomic_list_concat([Old, Sep, Dir], New),
 3979            (   debugging(jpl(path))
 3980            ->  env_var_separators(A,Z),
 3981                debug(jpl(path), 'Set ~w~w~w to ~p', [A,Path,Z,New])
 3982            ;   true
 3983            ),
 3984            setenv(Path, New)
 3985        )
 3986    ;   setenv(Path, Dir)
 3987    ).
 search_path_separator(-Sep:atom)
Separator used the the OS in PATH, LD_LIBRARY_PATH, CLASSPATH, etc.
 3994search_path_separator((;)) :-
 3995    current_prolog_flag(windows, true),
 3996    !.
 3997search_path_separator(:).
 3998
 3999env_var_separators('%','%') :-
 4000    current_prolog_flag(windows, true),
 4001    !.
 4002env_var_separators($,'').
 4003
 4004
 4005         /*******************************
 4006         *         LOAD THE JVM         *
 4007         *******************************/
 check_java_environment
Verify the Java environment. Preferably we would create, but most Unix systems do not allow putenv("LD_LIBRARY_PATH=..." in the current process. A suggesting found on the net is to modify LD_LIBRARY_PATH right at startup and next execv() yourself, but this doesn't work if we want to load Java on demand or if Prolog itself is embedded in another application.

So, after reading lots of pages on the web, I decided checking the environment and producing a sensible error message is the best we can do.

Please not that Java2 doesn't require $CLASSPATH to be set, so we do not check for that.

 4025check_java_environment :-
 4026    current_prolog_flag(apple, true),
 4027    !,
 4028    print_message(error, jpl(run(jpl_config_dylib))).
 4029check_java_environment :-
 4030    check_lib(jvm).
 4031
 4032check_lib(Name) :-
 4033    check_shared_object(Name, File, EnvVar, Absolute),
 4034    (   Absolute == (-)
 4035    ->  env_var_separators(A, Z),
 4036        format(string(Msg), 'Please add directory holding ~w to ~w~w~w',
 4037               [ File, A, EnvVar, Z ]),
 4038        throw(error(existence_error(library, Name),
 4039                    context(_, Msg)))
 4040    ;   true
 4041    ).
 check_shared_object(+Lib, -File, -EnvVar, -AbsFile) is semidet
True if AbsFile is existing .so/.dll file for Lib.
Arguments:
File- Full name of Lib (i.e. libjpl.so or jpl.dll)
EnvVar- Search-path for shared objects.
 4050check_shared_object(Name, File, EnvVar, Absolute) :-
 4051    libfile(Name, File),
 4052    library_search_path(Path, EnvVar),
 4053    (   member(Dir, Path),
 4054        atomic_list_concat([Dir, File], /, Absolute),
 4055        exists_file(Absolute)
 4056    ->  true
 4057    ;   Absolute = (-)
 4058    ).
 4059
 4060libfile(Base, File) :-
 4061    current_prolog_flag(unix, true),
 4062    !,
 4063    atom_concat(lib, Base, F0),
 4064    current_prolog_flag(shared_object_extension, Ext),
 4065    file_name_extension(F0, Ext, File).
 4066libfile(Base, File) :-
 4067    current_prolog_flag(windows, true),
 4068    !,
 4069    current_prolog_flag(shared_object_extension, Ext),
 4070    file_name_extension(Base, Ext, File).
 library_search_path(-Dirs:list, -EnvVar) is det
Dirs is the list of directories searched for shared objects/DLLs. EnvVar is the variable in which the search path os stored.
 4078library_search_path(Path, EnvVar) :-
 4079    current_prolog_flag(shared_object_search_path, EnvVar),
 4080    search_path_separator(Sep),
 4081    (   getenv(EnvVar, Env),
 4082        atomic_list_concat(Path, Sep, Env)
 4083    ->  true
 4084    ;   Path = []
 4085    ).
 add_jpl_to_classpath
Add jpl.jar to CLASSPATH to facilitate callbacks. If jpl.jar is already in CLASSPATH, do nothing. Note that this may result in the user picking up a different version of jpl.jar. We'll assume the user is right in this case.
To be done
- Should we warn if both classpath and jar return a result that is different? What is different? According to same_file/2 or content?
 4099add_jpl_to_classpath :-
 4100    classpath(Jar),
 4101    file_base_name(Jar, 'jpl.jar'),
 4102    !.
 4103add_jpl_to_classpath :-
 4104    classpath(Dir),
 4105    directory_file_path(Dir, 'jpl.jar', File),
 4106    access_file(File, read),
 4107    !.
 4108add_jpl_to_classpath :-
 4109    absolute_file_name(jar('jpl.jar'), JplJAR,
 4110                       [ access(read)
 4111                       ]),
 4112    !,
 4113    (   getenv('CLASSPATH', Old)
 4114    ->  search_path_separator(Separator),
 4115        atomic_list_concat([JplJAR, Old], Separator, New)
 4116    ;   New = JplJAR
 4117    ),
 4118    setenv('CLASSPATH', New).
 libjpl(-Spec) is det
Return the spec for loading the JPL shared object. This shared object must be called libjpl.so as the Java System.loadLibrary() call used by jpl.jar adds the lib* prefix.
 4127libjpl(File) :-
 4128    (   current_prolog_flag(unix, true)
 4129    ->  File = foreign(libjpl)
 4130    ;   File = foreign(jpl)
 4131    ).
 add_jpl_to_ldpath(+JPL) is det
Add the directory holding jpl.so to search path for dynamic libraries. This is needed for callback from Java. Java appears to use its own search and the new value of the variable is picked up correctly.
 4140add_jpl_to_ldpath(JPL) :-
 4141    absolute_file_name(JPL, File,
 4142               [ file_type(executable),
 4143                 access(read),
 4144                 file_errors(fail)
 4145               ]),
 4146    !,
 4147    file_directory_name(File, Dir),
 4148    prolog_to_os_filename(Dir, OsDir),
 4149    extend_java_library_path(OsDir),
 4150    current_prolog_flag(shared_object_search_path, PathVar),
 4151    add_search_path(PathVar, OsDir).
 4152add_jpl_to_ldpath(_).
 add_java_to_ldpath is det
Adds the directories holding jvm.dll to the %PATH%. This appears to work on Windows. Unfortunately most Unix systems appear to inspect the content of LD_LIBRARY_PATH (DYLD_LIBRARY_PATH on MacOS) only once.
 4161:- if(current_prolog_flag(windows,true)). 4162add_java_to_ldpath :-
 4163    current_prolog_flag(windows, true),
 4164    !,
 4165    phrase(java_dirs, Extra),
 4166    (   Extra \== []
 4167    ->  print_message(informational, extend_ld_path(Extra)),
 4168        maplist(extend_dll_search_path, Extra)
 4169    ;   true
 4170    ).
 4171:- endif. 4172add_java_to_ldpath.
 extend_dll_search_path(+Dir)
Add Dir to search for DLL files. We use win_add_dll_directory/1, but this doesn't seem to work on Wine, so we also add these directories to %PATH% on this platform.
 4181:- if(current_prolog_flag(windows,true)). 4182extend_dll_search_path(Dir) :-
 4183    win_add_dll_directory(Dir),
 4184    (   current_prolog_flag(wine_version, _)
 4185    ->  getenv('PATH', Path0),
 4186        prolog_to_os_filename(Dir, OSDir),
 4187        atomic_list_concat([Path0, OSDir], ';', Path),
 4188        setenv('PATH', Path)
 4189    ;   true
 4190    ).
 4191:- endif.
 extend_java_library_path(+OsDir)
Add Dir (in OS notation) to the Java -Djava.library.path init options.
 4198extend_java_library_path(OsDir) :-
 4199    jpl_get_default_jvm_opts(Opts0),
 4200    (   select(PathOpt0, Opts0, Rest),
 4201        sub_atom(PathOpt0, 0, _, _, '-Djava.library.path=')
 4202    ->  search_path_separator(Separator),
 4203        atomic_list_concat([PathOpt0, Separator, OsDir], PathOpt),
 4204        NewOpts = [PathOpt|Rest]
 4205    ;   atom_concat('-Djava.library.path=', OsDir, PathOpt),
 4206        NewOpts = [PathOpt|Opts0]
 4207    ),
 4208    debug(jpl(path), 'Setting Java options to ~p', [NewOpts]),
 4209    jpl_set_default_jvm_opts(NewOpts).
 java_dirs// is det
DCG that produces existing candidate directories holding Java related DLLs
 4216java_dirs -->
 4217    % JDK directories
 4218    java_dir(jvm, '/jre/bin/client'),
 4219    java_dir(jvm, '/jre/bin/server'),
 4220    java_dir(java, '/jre/bin'),
 4221    % JRE directories
 4222    java_dir(jvm, '/bin/client'),
 4223    java_dir(jvm, '/bin/server'),
 4224    java_dir(java, '/bin').
 4225
 4226java_dir(DLL, _SubPath) -->
 4227    { check_shared_object(DLL, _, _Var, Abs),
 4228      Abs \== (-)
 4229    },
 4230    !.
 4231java_dir(_DLL, SubPath) -->
 4232    { java_home(JavaHome),
 4233      atom_concat(JavaHome, SubPath, SubDir),
 4234      exists_directory(SubDir)
 4235    },
 4236    !,
 4237    [SubDir].
 4238java_dir(_, _) --> [].
 java_home(-Home) is semidet
Find the home location of Java.
Arguments:
Home- JAVA home in OS notation
 4247java_home_win_key(
 4248    jre,
 4249    'HKEY_LOCAL_MACHINE/Software/JavaSoft/Java Runtime Environment').
 4250java_home_win_key(
 4251    jdk,
 4252    'HKEY_LOCAL_MACHINE/Software/JavaSoft/Java Development Kit').
 4253
 4254java_home(Home) :-
 4255    getenv('JAVA_HOME', Home),
 4256    exists_directory(Home),
 4257    !.
 4258:- if(current_prolog_flag(windows, true)). 4259java_home(Home) :-
 4260    java_home_win_key(_, Key0),    % TBD: user can't choose jre or jdk
 4261    catch(win_registry_get_value(Key0, 'CurrentVersion', Version), _, fail),
 4262    atomic_list_concat([Key0, Version], /, Key),
 4263    win_registry_get_value(Key, 'JavaHome', WinHome),
 4264    prolog_to_os_filename(Home, WinHome),
 4265    exists_directory(Home),
 4266    !.
 4267:- else. 4268java_home(Home) :-
 4269    member(Home, [ '/usr/lib/java',
 4270                   '/usr/local/lib/java'
 4271                 ]),
 4272    exists_directory(Home),
 4273    !.
 4274:- endif. 4275
 4276:- dynamic
 4277    jvm_ready/0. 4278:- volatile
 4279    jvm_ready/0. 4280
 4281setup_jvm :-
 4282    jvm_ready,
 4283    !.
 4284setup_jvm :-
 4285    add_jpl_to_classpath,
 4286    add_java_to_ldpath,
 4287    libjpl(JPL),
 4288    catch(load_foreign_library(JPL), E, report_java_setup_problem(E)),
 4289    add_jpl_to_ldpath(JPL),
 4290    assert(jvm_ready).
 4291
 4292report_java_setup_problem(E) :-
 4293    print_message(error, E),
 4294    check_java_environment.
 4295
 4296         /*******************************
 4297         *          MESSAGES        *
 4298         *******************************/
 4299
 4300:- multifile
 4301    prolog:message//1. 4302
 4303prolog:message(extend_ld_path(Dirs)) -->
 4304    [ 'Extended DLL search path with'-[] ],
 4305    dir_per_line(Dirs).
 4306prolog:message(jpl(run(Command))) -->
 4307    [ 'Could not find libjpl.dylib dependencies.'-[],
 4308      'Please run `?- ~p.` to correct this'-[Command]
 4309    ].
 4310
 4311dir_per_line([]) --> [].
 4312dir_per_line([H|T]) -->
 4313    [ nl, '  ~q'-[H] ],
 4314    dir_per_line(T).
 4315
 4316% Initialize JVM
 4317
 4318:- initialization(setup_jvm, now).        % must be ready before export