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:- autoload(library(apply),[maplist/2]).   86:- autoload(library(debug),[debugging/1,debug/3]).   87:- autoload(library(filesex),[directory_file_path/3]).   88:- autoload(library(lists),
   89	    [member/2,nth0/3,nth1/3,append/3,flatten/2,select/3]).   90:- autoload(library(shlib),[load_foreign_library/1]).

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/ */
   99% suppress debugging this library
  100:- 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.

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

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

  308jpl_call(X, Mspec, Params, R) :-
  309    (   jpl_object_to_type(X, Type)         % the usual case (goal fails safely if X is var or rubbish)
  310    ->  Obj = X,
  311        Kind = instance
  312    ;   var(X)
  313    ->  throw(error(instantiation_error,context(jpl_call/4,'1st arg must be bound to an object, classname, descriptor or type')))
  314    ;   atom(X)
  315    ->  (   jpl_classname_to_type(X, Type)     % does this attempt to load the class?
  316        ->  (   jpl_type_to_class(Type, ClassObj)
  317            ->  Kind = static
  318            ;   throw(error(existence_error(class,X),context(jpl_call/4,'the named class cannot be found')))
  319            )
  320        ;   throw(error(type_error(class_name_or_descriptor,X),context(jpl_call/4,'1st arg must be an object, classname, descriptor or type')))
  321        )
  322    ;   X = class(_,_)
  323    ->  Type = X,
  324        jpl_type_to_class(Type, ClassObj),
  325        Kind = static
  326    ;   X = array(_)
  327    ->  throw(error(type_error(object_or_class,X),context(jpl_call/4,'cannot call a static method of an array type, as none exists')))
  328    ;   throw(error(domain_error(object_or_class,X),context(jpl_call/4,'1st arg must be an object, classname, descriptor or type')))
  329    ),
  330    (   atom(Mspec)                 % the usual case, i.e. a method name
  331    ->  true
  332    ;   var(Mspec)
  333    ->  throw(error(instantiation_error,context(jpl_call/4,'2nd arg must be an atom naming a public method of the class or object')))
  334    ;   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')))
  335    ),
  336    (   is_list(Params)
  337    ->  (   catch(
  338                jpl_datums_to_types(Params, Taps),
  339                error(type_error(acyclic,Te),context(jpl_datum_to_type/2,Msg)),
  340                throw(error(type_error(acyclic,Te),context(jpl_call/4,Msg)))
  341            )
  342        ->  true
  343        ;   throw(error(type_error(method_params,Params),context(jpl_call/4,'not all actual parameters are convertible to Java values or references')))
  344        ),
  345        length(Params, A)
  346    ;   var(Params)
  347    ->  throw(error(instantiation_error,context(jpl_call/4,'3rd arg must be a proper list of actual parameters for the named method')))
  348    ;   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')))
  349    ),
  350    (   Kind == instance
  351    ->  jpl_call_instance(Type, Obj, Mspec, Params, Taps, A, Rx)
  352    ;   jpl_call_static(Type, ClassObj, Mspec, Params, Taps, A, Rx)
  353    ),
  354    (   nonvar(R),
  355        R = {Term}  % yucky way of requesting Term->term conversion
  356    ->  (   jni_jref_to_term(Rx, TermX)    % fails if Rx isn't a JRef to a org.jpl7.Term
  357        ->  Term = TermX
  358        ;   throw(error(type_error,context(jpl_call/4,'result is not a org.jpl7.Term instance as required')))
  359        )
  360    ;   R = Rx
  361    ).
 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.
  371jpl_call_instance(Type, Obj, Mname, Params, Taps, A, Rx) :-
  372    findall(                    % get remaining details of all accessible methods of Obj's class (as denoted by Type)
  373        z5(I,Mods,MID,Tr,Tfps),
  374        jpl_method_spec(Type, I, Mname, A, Mods, MID, Tr, Tfps),
  375        Z5s
  376    ),
  377    (   Z5s = []
  378    ->  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')))
  379    ;   findall(
  380            z5(I,Mods,MID,Tr,Tfps),             % those to which Params is assignable
  381            (   member(z5(I,Mods,MID,Tr,Tfps), Z5s),
  382                jpl_types_fit_types(Taps, Tfps) % assignability test: actual param types "fit" formal param types
  383            ),
  384            Z5sA                                % Params-assignable methods
  385        ),
  386        (   Z5sA == []
  387        ->  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')))
  388        ;   Z5sA = [z5(I,Mods,MID,Tr,Tfps)]
  389        ->  true                                % exactly one applicable method
  390        ;   jpl_z5s_to_most_specific_z5(Z5sA, z5(I,Mods,MID,Tr,Tfps))
  391        ->  true                                % exactly one most-specific applicable method
  392        ;   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)')))
  393        )
  394    ),
  395    (   member(static, Mods)                                        % if the chosen method is static
  396    ->  jpl_object_to_class(Obj, ClassObj),                         % get a java.lang.Class instance which personifies Obj's class
  397        jpl_call_static_method(Tr, ClassObj, MID, Tfps, Params, Rx) % call static method w.r.t. associated Class object
  398    ;   jpl_call_instance_method(Tr, Obj, MID, Tfps, Params, Rx)    % else call (non-static) method w.r.t. object itself
  399    ).
 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.
  410jpl_call_static(Type, ClassObj, Mname, Params, Taps, A, Rx) :-
  411    findall(                    % get all accessible static methods of the class denoted by Type and ClassObj
  412        z5(I,Mods,MID,Tr,Tfps),
  413        (   jpl_method_spec(Type, I, Mname, A, Mods, MID, Tr, Tfps),
  414            member(static, Mods)
  415        ),
  416        Z5s
  417    ),
  418    (   Z5s = []
  419    ->  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')))
  420    ;   findall(
  421            z5(I,Mods,MID,Tr,Tfps),
  422            (   member(z5(I,Mods,MID,Tr,Tfps), Z5s),
  423                jpl_types_fit_types(Taps, Tfps) % assignability test: actual param types "fit" formal param types
  424            ),
  425            Z5sA                                % Params-assignable methods
  426        ),
  427        (   Z5sA == []
  428        ->  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')))
  429        ;   Z5sA = [z5(I,Mods,MID,Tr,Tfps)]
  430        ->  true                % exactly one applicable method
  431        ;   jpl_z5s_to_most_specific_z5(Z5sA, z5(I,Mods,MID,Tr,Tfps))
  432        ->  true                % exactly one most-specific applicable method
  433        ;   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)')))
  434        )
  435    ),
  436    jpl_call_static_method(Tr, ClassObj, MID, Tfps, Params, Rx).
 jpl_call_instance_method(+Type, +ClassObject, +MethodID, +FormalParamTypes, +Params, -Result)
  441jpl_call_instance_method(void, Class, MID, Tfps, Ps, R) :-
  442    jCallVoidMethod(Class, MID, Tfps, Ps),
  443    jpl_void(R).
  444jpl_call_instance_method(boolean, Class, MID, Tfps, Ps, R) :-
  445    jCallBooleanMethod(Class, MID, Tfps, Ps, R).
  446jpl_call_instance_method(byte, Class, MID, Tfps, Ps, R) :-
  447    jCallByteMethod(Class, MID, Tfps, Ps, R).
  448jpl_call_instance_method(char, Class, MID, Tfps, Ps, R) :-
  449    jCallCharMethod(Class, MID, Tfps, Ps, R).
  450jpl_call_instance_method(short, Class, MID, Tfps, Ps, R) :-
  451    jCallShortMethod(Class, MID, Tfps, Ps, R).
  452jpl_call_instance_method(int, Class, MID, Tfps, Ps, R) :-
  453    jCallIntMethod(Class, MID, Tfps, Ps, R).
  454jpl_call_instance_method(long, Class, MID, Tfps, Ps, R) :-
  455    jCallLongMethod(Class, MID, Tfps, Ps, R).
  456jpl_call_instance_method(float, Class, MID, Tfps, Ps, R) :-
  457    jCallFloatMethod(Class, MID, Tfps, Ps, R).
  458jpl_call_instance_method(double, Class, MID, Tfps, Ps, R) :-
  459    jCallDoubleMethod(Class, MID, Tfps, Ps, R).
  460jpl_call_instance_method(array(_), Class, MID, Tfps, Ps, R) :-
  461    jCallObjectMethod(Class, MID, Tfps, Ps, R).
  462jpl_call_instance_method(class(_,_), Class, MID, Tfps, Ps, R) :-
  463    jCallObjectMethod(Class, MID, Tfps, Ps, R).
 jpl_call_static_method(+Type, +ClassObject, +MethodID, +FormalParamTypes, +Params, -Result)
  468jpl_call_static_method(void, Class, MID, Tfps, Ps, R) :-
  469    jCallStaticVoidMethod(Class, MID, Tfps, Ps),
  470    jpl_void(R).
  471jpl_call_static_method(boolean, Class, MID, Tfps, Ps, R) :-
  472    jCallStaticBooleanMethod(Class, MID, Tfps, Ps, R).
  473jpl_call_static_method(byte, Class, MID, Tfps, Ps, R) :-
  474    jCallStaticByteMethod(Class, MID, Tfps, Ps, R).
  475jpl_call_static_method(char, Class, MID, Tfps, Ps, R) :-
  476    jCallStaticCharMethod(Class, MID, Tfps, Ps, R).
  477jpl_call_static_method(short, Class, MID, Tfps, Ps, R) :-
  478    jCallStaticShortMethod(Class, MID, Tfps, Ps, R).
  479jpl_call_static_method(int, Class, MID, Tfps, Ps, R) :-
  480    jCallStaticIntMethod(Class, MID, Tfps, Ps, R).
  481jpl_call_static_method(long, Class, MID, Tfps, Ps, R) :-
  482    jCallStaticLongMethod(Class, MID, Tfps, Ps, R).
  483jpl_call_static_method(float, Class, MID, Tfps, Ps, R) :-
  484    jCallStaticFloatMethod(Class, MID, Tfps, Ps, R).
  485jpl_call_static_method(double, Class, MID, Tfps, Ps, R) :-
  486    jCallStaticDoubleMethod(Class, MID, Tfps, Ps, R).
  487jpl_call_static_method(array(_), Class, MID, Tfps, Ps, R) :-
  488    jCallStaticObjectMethod(Class, MID, Tfps, Ps, R).
  489jpl_call_static_method(class(_,_), Class, MID, Tfps, Ps, R) :-
  490    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].
  522jpl_get(X, Fspec, V) :-
  523    (   jpl_object_to_type(X, Type)
  524    ->  Obj = X,
  525        jpl_get_instance(Type, Type, Obj, Fspec, Vx)   % pass Type twice for FAI
  526    ;   var(X)
  527    ->  throw(error(instantiation_error,context(jpl_get/3,'1st arg must be bound to an object, classname, descriptor or type')))
  528    ;   jpl_is_type(X)          % e.g. class([java,lang],['String']), array(int)
  529    ->  Type = X,
  530        (   jpl_type_to_class(Type, ClassObj)
  531        ->  jpl_get_static(Type, ClassObj, Fspec, Vx)
  532        ;   jpl_type_to_classname(Type, Classname),
  533            throw(error(existence_error(class,Classname),context(jpl_get/3,'the named class cannot be found')))
  534        )
  535    ;   atom(X)
  536    ->  (   jpl_classname_to_type(X, Type)     % does this attempt to load the class?
  537        ->  (   jpl_type_to_class(Type, ClassObj)
  538            ->  jpl_get_static(Type, ClassObj, Fspec, Vx)
  539            ;   throw(error(existence_error(class,X),context(jpl_get/3,'the named class cannot be found')))
  540            )
  541        ;   throw(error(type_error(class_name_or_descriptor,X),context(jpl_get/3, '1st arg must be an object, classname, descriptor or type')))
  542        )
  543    ;   throw(error(domain_error(object_or_class,X),context(jpl_get/3,'1st arg must be bound to an object, classname, descriptor or type')))
  544    ),
  545    (   nonvar(V),
  546        V = {Term}  % yucky way of requesting Term->term conversion
  547    ->  (   jni_jref_to_term(Vx, TermX)    % fails if Rx is not a JRef to a org.jpl7.Term
  548        ->  Term = TermX
  549        ;   throw(error(type_error,context(jpl_call/4,'result is not a org.jpl7.Term instance as required')))
  550        )
  551    ;   V = Vx
  552    ).
 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
  562jpl_get_static(Type, ClassObj, Fname, Vx) :-
  563    (   atom(Fname)             % assume it's a field name
  564    ->  true
  565    ;   var(Fname)
  566    ->  throw(error(instantiation_error,context(jpl_get/3,'2nd arg must be bound to an atom naming a public field of the class')))
  567    ;   throw(error(type_error(field_name,Fname),context(jpl_get/3,'2nd arg must be an atom naming a public field of the class')))
  568    ),
  569  % get static fields of the denoted class
  570    findall(
  571        z4(I,Mods,FID,Tf),
  572        (   jpl_field_spec(Type, I, Fname, Mods, FID, Tf),
  573            member(static, Mods)
  574        ),
  575        Z4s
  576    ),
  577    (   Z4s = []
  578    ->  throw(error(existence_error(field,Fname),context(jpl_get/3,'the class or object has no public static field with the given name')))
  579    ;   Z4s = [z4(I,_Mods,FID,Tf)]
  580    ->  jpl_get_static_field(Tf, ClassObj, FID, Vx)
  581    ;   throw(error(existence_error(unique_field,Fname),context(jpl_get/3,'more than one field is found with the given name')))
  582    ).
 jpl_get_instance(+Type, +Type, +Object, +FieldSpecifier, -Value) is det
  587jpl_get_instance(class(_,_), Type, Obj, Fname, Vx) :-
  588    (   atom(Fname)                 % the usual case
  589    ->  true
  590    ;   var(Fname)
  591    ->  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')))
  592    ;   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')))
  593    ),
  594    findall(
  595        z4(I,Mods,FID,Tf),
  596        jpl_field_spec(Type, I, Fname, Mods, FID, Tf),
  597        Z4s
  598    ),
  599    (   Z4s = []
  600    ->  throw(error(existence_error(field,Fname),context(jpl_get/3,'the class or object has no public field with the given name')))
  601    ;   Z4s = [z4(I,Mods,FID,Tf)]
  602    ->  (   member(static, Mods)
  603        ->  jpl_object_to_class(Obj, ClassObj),
  604            jpl_get_static_field(Tf, ClassObj, FID, Vx)
  605        ;   jpl_get_instance_field(Tf, Obj, FID, Vx)
  606        )
  607    ;   throw(error(existence_error(unique_field,Fname),context(jpl_get/3,'more than one field is found with the given name')))
  608    ).
  609jpl_get_instance(array(ElementType), _, Array, Fspec, Vx) :-
  610    (   var(Fspec)
  611    ->  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''')))
  612    ;   integer(Fspec)
  613    ->  (   Fspec < 0       % lo bound check
  614        ->  throw(error(domain_error(array_index,Fspec),context(jpl_get/3,'when 1st arg is an array, integral 2nd arg must be non-negative')))
  615        ;   jGetArrayLength(Array, Len),
  616            Fspec >= Len    % hi bound check
  617        ->  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')))
  618        ;   jpl_get_array_element(ElementType, Array, Fspec, Vx)
  619        )
  620    ;   Fspec = N-M     % NB should we support e.g. 3-2 -> [] ?
  621    ->  (   integer(N),
  622            integer(M)
  623        ->  (   N >= 0,
  624                M >= N
  625            ->  jGetArrayLength(Array, Len),
  626                (   N >= Len
  627                ->  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')))
  628                ;   M >= Len
  629                ->  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')))
  630                ;   jpl_get_array_elements(ElementType, Array, N, M, Vx)
  631                )
  632            ;   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')))
  633            )
  634        ;   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')))
  635        )
  636    ;   atom(Fspec)
  637    ->  (   Fspec == length             % special-case for this solitary array "method"
  638        ->  jGetArrayLength(Array, Vx)
  639        ;   throw(error(domain_error(array_field_name,Fspec),context(jpl_get/3,'the array has no public field with the given name')))
  640        )
  641    ;   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''')))
  642    ).
 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
  654jpl_get_array_element(Type, Array, Index, Vc) :-
  655    (   (   Type = class(_,_)
  656        ;   Type = array(_)
  657        )
  658    ->  jGetObjectArrayElement(Array, Index, Vr)
  659    ;   jpl_primitive_type(Type)
  660    ->  jni_type_to_xput_code(Type, Xc),
  661        jni_alloc_buffer(Xc, 1, Bp),        % one-element buf for a Type
  662        jpl_get_primitive_array_region(Type, Array, Index, 1, Bp),
  663        jni_fetch_buffer_value(Bp, 0, Vr, Xc),    % zero-th element
  664        jni_free_buffer(Bp)
  665    ),
  666    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

  675jpl_get_array_elements(ElementType, Array, N, M, Vs) :-
  676    (   (   ElementType = class(_,_)
  677        ;   ElementType = array(_)
  678        )
  679    ->  jpl_get_object_array_elements(Array, N, M, Vs)
  680    ;   jpl_get_primitive_array_elements(ElementType, Array, N, M, Vs)
  681    ).
  682
  683
  684jpl_get_instance_field(boolean, Obj, FieldID, V) :-
  685    jGetBooleanField(Obj, FieldID, V).
  686jpl_get_instance_field(byte, Obj, FieldID, V) :-
  687    jGetByteField(Obj, FieldID, V).
  688jpl_get_instance_field(char, Obj, FieldID, V) :-
  689    jGetCharField(Obj, FieldID, V).
  690jpl_get_instance_field(short, Obj, FieldID, V) :-
  691    jGetShortField(Obj, FieldID, V).
  692jpl_get_instance_field(int, Obj, FieldID, V) :-
  693    jGetIntField(Obj, FieldID, V).
  694jpl_get_instance_field(long, Obj, FieldID, V) :-
  695    jGetLongField(Obj, FieldID, V).
  696jpl_get_instance_field(float, Obj, FieldID, V) :-
  697    jGetFloatField(Obj, FieldID, V).
  698jpl_get_instance_field(double, Obj, FieldID, V) :-
  699    jGetDoubleField(Obj, FieldID, V).
  700jpl_get_instance_field(class(_,_), Obj, FieldID, V) :-
  701    jGetObjectField(Obj, FieldID, V).
  702jpl_get_instance_field(array(_), Obj, FieldID, V) :-
  703    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
  715jpl_get_object_array_elements(Array, Lo, Hi, Vcs) :-
  716    (   Lo =< Hi
  717    ->  Vcs = [Vc|Vcs2],
  718        jGetObjectArrayElement(Array, Lo, Vc),
  719        Next is Lo+1,
  720        jpl_get_object_array_elements(Array, Next, Hi, Vcs2)
  721    ;   Vcs = []
  722    ).
 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
  732jpl_get_primitive_array_elements(ElementType, Array, Lo, Hi, Vcs) :-
  733    Size is Hi-Lo+1,
  734    (   Size == 0
  735    ->  Vcs = []
  736    ;   jni_type_to_xput_code(ElementType, Xc),
  737        jni_alloc_buffer(Xc, Size, Bp),
  738        jpl_get_primitive_array_region(ElementType, Array, Lo, Size, Bp),
  739        jpl_primitive_buffer_to_array(ElementType, Xc, Bp, 0, Size, Vcs),
  740        jni_free_buffer(Bp)
  741    ).
  742
  743
  744jpl_get_primitive_array_region(boolean, Array, Lo, S, I) :-
  745    jGetBooleanArrayRegion(Array, Lo, S, jbuf(I,boolean)).
  746jpl_get_primitive_array_region(byte, Array, Lo, S, I) :-
  747    jGetByteArrayRegion(Array, Lo, S, jbuf(I,byte)).
  748jpl_get_primitive_array_region(char, Array, Lo, S, I) :-
  749    jGetCharArrayRegion(Array, Lo, S, jbuf(I,char)).
  750jpl_get_primitive_array_region(short, Array, Lo, S, I) :-
  751    jGetShortArrayRegion(Array, Lo, S, jbuf(I,short)).
  752jpl_get_primitive_array_region(int, Array, Lo, S, I) :-
  753    jGetIntArrayRegion(Array, Lo, S, jbuf(I,int)).
  754jpl_get_primitive_array_region(long, Array, Lo, S, I) :-
  755    jGetLongArrayRegion(Array, Lo, S, jbuf(I,long)).
  756jpl_get_primitive_array_region(float, Array, Lo, S, I) :-
  757    jGetFloatArrayRegion(Array, Lo, S, jbuf(I,float)).
  758jpl_get_primitive_array_region(double, Array, Lo, S, I) :-
  759    jGetDoubleArrayRegion(Array, Lo, S, jbuf(I,double)).
  760
  761
  762jpl_get_static_field(boolean, Array, FieldID, V) :-
  763    jGetStaticBooleanField(Array, FieldID, V).
  764jpl_get_static_field(byte, Array, FieldID, V) :-
  765    jGetStaticByteField(Array, FieldID, V).
  766jpl_get_static_field(char, Array, FieldID, V) :-
  767    jGetStaticCharField(Array, FieldID, V).
  768jpl_get_static_field(short, Array, FieldID, V) :-
  769    jGetStaticShortField(Array, FieldID, V).
  770jpl_get_static_field(int, Array, FieldID, V) :-
  771    jGetStaticIntField(Array, FieldID, V).
  772jpl_get_static_field(long, Array, FieldID, V) :-
  773    jGetStaticLongField(Array, FieldID, V).
  774jpl_get_static_field(float, Array, FieldID, V) :-
  775    jGetStaticFloatField(Array, FieldID, V).
  776jpl_get_static_field(double, Array, FieldID, V) :-
  777    jGetStaticDoubleField(Array, FieldID, V).
  778jpl_get_static_field(class(_,_), Array, FieldID, V) :-
  779    jGetStaticObjectField(Array, FieldID, V).
  780jpl_get_static_field(array(_), Array, FieldID, V) :-
  781    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.

  801jpl_set(X, Fspec, V) :-
  802    (   jpl_object_to_type(X, Type)         % the usual case (test is safe if X is var or rubbish)
  803    ->  Obj = X,
  804        catch(
  805            jpl_set_instance(Type, Type, Obj, Fspec, V),    % first 'Type' is for FAI
  806            error(type_error(acyclic,Te),context(jpl_datum_to_type/2,Msg)),
  807            throw(error(type_error(acyclic,Te),context(jpl_set/3,Msg)))
  808        )
  809    ;   var(X)
  810    ->  throw(error(instantiation_error,context(jpl_set/3,'1st arg must be an object, classname, descriptor or type')))
  811    ;   (   atom(X)
  812        ->  (   jpl_classname_to_type(X, Type)          % it's a classname or descriptor...
  813            ->  true
  814            ;   throw(error(existence_error(class,X),context(jpl_set/3,'the named class cannot be found')))
  815            )
  816        ;   (   X = class(_,_)                          % it's a class type...
  817            ;   X = array(_)                            % ...or an array type
  818            )
  819        ->  Type = X
  820        ),
  821        (   jpl_type_to_class(Type, ClassObj)      % ...whose Class object is available
  822        ->  true
  823        ;   jpl_type_to_classname(Type, Classname),
  824            throw(error(existence_error(class,Classname),context(jpl_set/3,'the class cannot be found')))
  825        )
  826    ->  catch(
  827            jpl_set_static(Type, ClassObj, Fspec, V),
  828            error(type_error(acyclic,Te),context(jpl_datum_to_type/2,Msg)),
  829            throw(error(type_error(acyclic,Te),context(jpl_set/3,Msg)))
  830        )
  831    ;   throw(error(domain_error(object_or_class,X),context(jpl_set/3,'1st arg must be an object, classname, descriptor or type')))
  832    ).
 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

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

  933jpl_set_static(Type, ClassObj, Fname, V) :-
  934    (   atom(Fname)                     % the usual case
  935    ->  true
  936    ;   var(Fname)
  937    ->  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')))
  938    ;   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')))
  939    ),
  940    findall(  % get all static fields of the denoted class
  941        z4(I,Mods,FID,Tf),
  942        (   jpl_field_spec(Type, I, Fname, Mods, FID, Tf),
  943            member(static, Mods)
  944        ),
  945        Z4s
  946    ),
  947    (   Z4s = []
  948    ->  throw(error(existence_error(field,Fname),context(jpl_set/3,'class has no public static fields of this name')))
  949    ;   Z4s = [z4(I,Mods,FID,Tf)]       % exactly one synonymous field?
  950    ->  (   member(final, Mods)
  951        ->  throw(error(permission_error(modify,final_field,Fname),context(jpl_set/3,'cannot assign a value to a final field')))
  952        ;   jpl_datum_to_type(V, Tv)
  953        ->  (   jpl_type_fits_type(Tv, Tf)
  954            ->  jpl_set_static_field(Tf, ClassObj, FID, V)
  955            ;   jpl_type_to_nicename(Tf, NNf),
  956                throw(error(type_error(NNf,V),context(jpl_set/3,'the value is not assignable to the named field of the class')))
  957            )
  958        ;   throw(error(type_error(field_value,V),context(jpl_set/3,'3rd arg does not represent any Java value or object')))
  959        )
  960    ;   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)(?)')))
  961    ).
 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,_))
  971jpl_set_array(T, A, N, I, Ds) :-
  972    (   jpl_datums_to_types(Ds, Tds)        % most specialised types of given values
  973    ->  (   jpl_types_fit_type(Tds, T)      % all assignable to element type?
  974        ->  true
  975        ;   throw(error(type_error(array(T),Ds),context(jpl_set/3,'not all values are assignable to the array element type')))
  976        )
  977    ;   throw(error(type_error(array(T),Ds),context(jpl_set/3,'not all values are convertible to Java values or references')))
  978    ),
  979    (   (   T = class(_,_)
  980        ;   T = array(_)                    % array elements are objects
  981        )
  982    ->  (   nth0(J, Ds, D),                 % for each datum
  983            Nd is N+J,                      % compute array index
  984            (   D = {Tq}                    % quoted term?
  985            ->  jni_term_to_jref(Tq, D2)    % convert to a JPL reference to a corresponding org.jpl7.Term object
  986            ;   D = D2
  987            ),
  988            jSetObjectArrayElement(A, Nd, D2),
  989            fail                            % iterate
  990        ;   true
  991        )
  992    ;   jpl_primitive_type(T)               % array elements are primitive values
  993    ->  jni_type_to_xput_code(T, Xc),
  994        jni_alloc_buffer(Xc, I, Bp),        % I-element buf of required primitive type
  995        jpl_set_array_1(Ds, T, 0, Bp),
  996        jpl_set_elements(T, A, N, I, Bp),
  997        jni_free_buffer(Bp)
  998    ;   throw(error(system_error(array_element_type,T),context(jpl_set/3,'array element type is unknown (this should not happen)')))
  999    ).
 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...

 1010jpl_set_array_1([], _, _, _).
 1011jpl_set_array_1([V|Vs], Tprim, Ib, Bp) :-
 1012    jni_type_to_xput_code(Tprim, Xc),
 1013    jni_stash_buffer_value(Bp, Ib, V, Xc),
 1014    Ibnext is Ib+1,
 1015    jpl_set_array_1(Vs, Tprim, Ibnext, Bp).
 1016
 1017
 1018jpl_set_elements(boolean, Obj, N, I, Bp) :-
 1019    jSetBooleanArrayRegion(Obj, N, I, jbuf(Bp,boolean)).
 1020jpl_set_elements(char, Obj, N, I, Bp) :-
 1021    jSetCharArrayRegion(Obj, N, I, jbuf(Bp,char)).
 1022jpl_set_elements(byte, Obj, N, I, Bp) :-
 1023    jSetByteArrayRegion(Obj, N, I, jbuf(Bp,byte)).
 1024jpl_set_elements(short, Obj, N, I, Bp) :-
 1025    jSetShortArrayRegion(Obj, N, I, jbuf(Bp,short)).
 1026jpl_set_elements(int, Obj, N, I, Bp) :-
 1027    jSetIntArrayRegion(Obj, N, I, jbuf(Bp,int)).
 1028jpl_set_elements(long, Obj, N, I, Bp) :-
 1029    jSetLongArrayRegion(Obj, N, I, jbuf(Bp,long)).
 1030jpl_set_elements(float, Obj, N, I, Bp) :-
 1031    jSetFloatArrayRegion(Obj, N, I, jbuf(Bp,float)).
 1032jpl_set_elements(double, Obj, N, I, Bp) :-
 1033    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)
 1041jpl_set_instance_field(boolean, Obj, FieldID, V) :-
 1042    jSetBooleanField(Obj, FieldID, V).
 1043jpl_set_instance_field(byte, Obj, FieldID, V) :-
 1044    jSetByteField(Obj, FieldID, V).
 1045jpl_set_instance_field(char, Obj, FieldID, V) :-
 1046    jSetCharField(Obj, FieldID, V).
 1047jpl_set_instance_field(short, Obj, FieldID, V) :-
 1048    jSetShortField(Obj, FieldID, V).
 1049jpl_set_instance_field(int, Obj, FieldID, V) :-
 1050    jSetIntField(Obj, FieldID, V).
 1051jpl_set_instance_field(long, Obj, FieldID, V) :-
 1052    jSetLongField(Obj, FieldID, V).
 1053jpl_set_instance_field(float, Obj, FieldID, V) :-
 1054    jSetFloatField(Obj, FieldID, V).
 1055jpl_set_instance_field(double, Obj, FieldID, V) :-
 1056    jSetDoubleField(Obj, FieldID, V).
 1057jpl_set_instance_field(class(_,_), Obj, FieldID, V) :-  % also handles byval term assignments
 1058    (   V = {T}                     % quoted term?
 1059    ->  jni_term_to_jref(T, V2)     % convert to a JPL reference to a corresponding org.jpl7.Term object
 1060    ;   V = V2
 1061    ),
 1062    jSetObjectField(Obj, FieldID, V2).
 1063jpl_set_instance_field(array(_), Obj, FieldID, V) :-
 1064    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).
 1072jpl_set_static_field(boolean, Obj, FieldID, V) :-
 1073    jSetStaticBooleanField(Obj, FieldID, V).
 1074jpl_set_static_field(byte, Obj, FieldID, V) :-
 1075    jSetStaticByteField(Obj, FieldID, V).
 1076jpl_set_static_field(char, Obj, FieldID, V) :-
 1077    jSetStaticCharField(Obj, FieldID, V).
 1078jpl_set_static_field(short, Obj, FieldID, V) :-
 1079    jSetStaticShortField(Obj, FieldID, V).
 1080jpl_set_static_field(int, Obj, FieldID, V) :-
 1081    jSetStaticIntField(Obj, FieldID, V).
 1082jpl_set_static_field(long, Obj, FieldID, V) :-
 1083    jSetStaticLongField(Obj, FieldID, V).
 1084jpl_set_static_field(float, Obj, FieldID, V) :-
 1085    jSetStaticFloatField(Obj, FieldID, V).
 1086jpl_set_static_field(double, Obj, FieldID, V) :-
 1087    jSetStaticDoubleField(Obj, FieldID, V).
 1088jpl_set_static_field(class(_,_), Obj, FieldID, V) :-    % also handles byval term assignments
 1089    (   V = {T}                         % quoted term?
 1090    ->  jni_term_to_jref(T, V2)         % convert to a JPL reference to a corresponding org.jpl7.Term object
 1091    ;   V = V2
 1092    ),
 1093    jSetStaticObjectField(Obj, FieldID, V2).
 1094jpl_set_static_field(array(_), Obj, FieldID, V) :-
 1095    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']
 1103jpl_get_default_jvm_opts(Opts) :-
 1104    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.
 1111jpl_set_default_jvm_opts(Opts) :-
 1112    is_list(Opts),
 1113    length(Opts, N),
 1114    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.

 1123jpl_get_actual_jvm_opts(Opts) :-
 1124    jni_get_actual_jvm_opts(Opts).
 1125
 1126
 1127jpl_assert(Fact) :-
 1128    (   jpl_assert_policy(Fact, yes)
 1129    ->  assert(Fact)
 1130    ;   true
 1131    ).
 1132
 1133
 1134jpl_assert_policy(jpl_field_spec_cache(_,_,_,_,_,_), yes).
 1135jpl_assert_policy(jpl_method_spec_cache(_,_,_,_,_,_,_,_), yes).
 1136jpl_assert_policy(jpl_class_tag_type_cache(_,_), yes).
 1137jpl_assert_policy(jpl_classname_type_cache(_,_), yes).
 1138jpl_assert_policy(jpl_iref_type_cache(_,_), no).   % must correspond to JPL_CACHE_TYPE_OF_REF in jpl.c
 1139jpl_assert_policy(jpl_field_spec_is_cached(_), YN) :-
 1140    jpl_assert_policy(jpl_field_spec_cache(_,_,_,_,_,_), YN).
 1141jpl_assert_policy(jpl_method_spec_is_cached(_), YN) :-
 1142    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()

 1151jpl_tidy_iref_type_cache(Iref) :-
 1152  % write('[decaching types for iref='), write(Iref), write(']'), nl,
 1153    retractall(jpl_iref_type_cache(Iref,_)),
 1154    true.
 1155
 1156
 1157jpl_fergus_find_candidate([], Candidate, Candidate, []).
 1158jpl_fergus_find_candidate([X|Xs], Candidate0, Candidate, Rest) :-
 1159    (   jpl_fergus_greater(X, Candidate0)
 1160    ->  Candidate1 = X,
 1161        Rest = [Candidate0|Rest1]
 1162    ;   Candidate1 = Candidate0,
 1163        Rest = [X|Rest1]
 1164    ),
 1165    jpl_fergus_find_candidate(Xs, Candidate1, Candidate, Rest1).
 1166
 1167
 1168jpl_fergus_greater(z5(_,_,_,_,Tps1), z5(_,_,_,_,Tps2)) :-
 1169    jpl_types_fit_types(Tps1, Tps2).
 1170jpl_fergus_greater(z3(_,_,Tps1), z3(_,_,Tps2)) :-
 1171    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
 1182jpl_fergus_is_the_greatest([X|Xs], Greatest) :-
 1183    jpl_fergus_find_candidate(Xs, X, Greatest, Rest),
 1184    forall(
 1185        member(R, Rest),
 1186        jpl_fergus_greater(Greatest, R)
 1187    ).
 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).

 1197jpl_z3s_to_most_specific_z3(Zs, Z) :-
 1198    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)

 1208jpl_z5s_to_most_specific_z5(Zs, Z) :-
 1209    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'.
 1225jpl_pl_lib_version(VersionString) :-
 1226    jpl_pl_lib_version(Major, Minor, Patch, Status),
 1227    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.
 1244jpl_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)
 1273jpl_java_lib_version(V) :-
 1274    jpl_call('org.jpl7.JPL', version_string, [], V).
 jpl_pl_lib_path(-Path:atom)
 1279jpl_pl_lib_path(Path) :-
 1280    module_property(jpl, file(Path)).
 jpl_c_lib_path(-Path:atom)
 1285jpl_c_lib_path(Path) :-
 1286    shlib:current_library(_, _, Path, jpl, _),
 1287    !.
 jpl_java_lib_path(-Path:atom)
 1292jpl_java_lib_path(Path) :-
 1293    jpl_call('org.jpl7.JPL', jarPath, [], Path).
 1294
 1295
 1296% jpl_type_alfa(0'$) -->        % presumably not allowed
 1297%   "$".                        % given the "inner class" syntax?
 1298
 1299jpl_type_alfa(0'_) -->
 1300    "_",
 1301    !.
 1302jpl_type_alfa(C) -->
 1303    [C], { C>=0'a, C=<0'z },
 1304    !.
 1305jpl_type_alfa(C) -->
 1306    [C], { C>=0'A, C=<0'Z }.
 1307
 1308
 1309jpl_type_alfa_num(C) -->
 1310    jpl_type_alfa(C),
 1311    !.
 1312jpl_type_alfa_num(C) -->
 1313    [C], { C>=0'0, C=<0'9 }.
 1314
 1315
 1316jpl_type_array_classname(array(T)) -->
 1317    "[", jpl_type_classname_2(T).
 1318
 1319
 1320jpl_type_array_descriptor(array(T)) -->
 1321    "[", jpl_type_descriptor_1(T).
 1322
 1323
 1324jpl_type_bare_class_descriptor(class(Ps,Cs)) -->
 1325    jpl_type_slashed_package_parts(Ps), jpl_type_class_parts(Cs).
 1326
 1327
 1328jpl_type_bare_classname(class(Ps,Cs)) -->
 1329    jpl_type_dotted_package_parts(Ps), jpl_type_class_parts(Cs).
 1330
 1331
 1332jpl_type_class_descriptor(class(Ps,Cs)) -->
 1333    "L", jpl_type_bare_class_descriptor(class(Ps,Cs)), ";".
 1334
 1335
 1336jpl_type_class_part(N) -->
 1337    jpl_type_id(N).
 1338
 1339
 1340jpl_type_class_parts([C|Cs]) -->
 1341    jpl_type_class_part(C), jpl_type_inner_class_parts(Cs).
 1342
 1343
 1344jpl_type_classname_1(T) -->
 1345    jpl_type_bare_classname(T),
 1346    !.
 1347jpl_type_classname_1(T) -->
 1348    jpl_type_array_classname(T),
 1349    !.
 1350jpl_type_classname_1(T) -->
 1351    jpl_type_primitive(T).
 1352
 1353
 1354jpl_type_classname_2(T) -->
 1355    jpl_type_delimited_classname(T).
 1356jpl_type_classname_2(T) -->
 1357    jpl_type_array_classname(T).
 1358jpl_type_classname_2(T) -->
 1359    jpl_type_primitive(T).
 1360
 1361
 1362
 1363jpl_type_delimited_classname(Class) -->
 1364    "L", jpl_type_bare_classname(Class), ";".
 1365
 1366
 1367
 1368jpl_type_descriptor_1(T) -->
 1369    jpl_type_primitive(T),
 1370    !.
 1371jpl_type_descriptor_1(T) -->
 1372    jpl_type_class_descriptor(T),
 1373    !.
 1374jpl_type_descriptor_1(T) -->
 1375    jpl_type_array_descriptor(T),
 1376    !.
 1377jpl_type_descriptor_1(T) -->
 1378    jpl_type_method_descriptor(T).
 1379
 1380
 1381
 1382jpl_type_dotted_package_parts([P|Ps]) -->
 1383    jpl_type_package_part(P), ".", !, jpl_type_dotted_package_parts(Ps).
 1384jpl_type_dotted_package_parts([]) -->
 1385    [].
 1386
 1387
 1388
 1389jpl_type_findclassname(T) -->
 1390    jpl_type_bare_class_descriptor(T).
 1391jpl_type_findclassname(T) -->
 1392    jpl_type_array_descriptor(T).
 1393
 1394
 1395
 1396jpl_type_id(A) -->
 1397    { nonvar(A) -> atom_codes(A,[C|Cs]) ; true },
 1398    jpl_type_alfa(C), jpl_type_id_rest(Cs),
 1399    { atom_codes(A, [C|Cs]) }.
 1400
 1401
 1402
 1403jpl_type_id_rest([C|Cs]) -->
 1404    jpl_type_alfa_num(C), !, jpl_type_id_rest(Cs).
 1405jpl_type_id_rest([]) -->
 1406    [].
 1407
 1408
 1409
 1410jpl_type_id_v2(A) -->                   % inner class name parts (empirically)
 1411    { nonvar(A) -> atom_codes(A,Cs) ; true },
 1412    jpl_type_id_rest(Cs),
 1413    { atom_codes(A, Cs) }.
 1414
 1415
 1416
 1417jpl_type_inner_class_part(N) -->
 1418    jpl_type_id_v2(N).
 1419
 1420
 1421
 1422jpl_type_inner_class_parts([C|Cs]) -->
 1423    "$", jpl_type_inner_class_part(C), !, jpl_type_inner_class_parts(Cs).
 1424jpl_type_inner_class_parts([]) -->
 1425    [].
 1426
 1427
 1428
 1429jpl_type_method_descriptor(method(Ts,T)) -->
 1430    "(", jpl_type_method_descriptor_args(Ts), ")", jpl_type_method_descriptor_return(T).
 1431
 1432
 1433
 1434jpl_type_method_descriptor_args([T|Ts]) -->
 1435    jpl_type_descriptor_1(T), !, jpl_type_method_descriptor_args(Ts).
 1436jpl_type_method_descriptor_args([]) -->
 1437    [].
 1438
 1439
 1440
 1441jpl_type_method_descriptor_return(T) -->
 1442    jpl_type_void(T).
 1443jpl_type_method_descriptor_return(T) -->
 1444    jpl_type_descriptor_1(T).
 1445
 1446
 1447
 1448jpl_type_package_part(N) -->
 1449    jpl_type_id(N).
 1450
 1451
 1452
 1453jpl_type_primitive(boolean) -->
 1454    "Z",
 1455    !.
 1456jpl_type_primitive(byte) -->
 1457    "B",
 1458    !.
 1459jpl_type_primitive(char) -->
 1460    "C",
 1461    !.
 1462jpl_type_primitive(short) -->
 1463    "S",
 1464    !.
 1465jpl_type_primitive(int) -->
 1466    "I",
 1467    !.
 1468jpl_type_primitive(long) -->
 1469    "J",
 1470    !.
 1471jpl_type_primitive(float) -->
 1472    "F",
 1473    !.
 1474jpl_type_primitive(double) -->
 1475    "D".
 1476
 1477
 1478
 1479jpl_type_slashed_package_parts([P|Ps]) -->
 1480    jpl_type_package_part(P), "/", !, jpl_type_slashed_package_parts(Ps).
 1481jpl_type_slashed_package_parts([]) -->
 1482    [].
 1483
 1484
 1485
 1486jpl_type_void(void) -->
 1487    "V".
 jCallBooleanMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rbool:boolean)
 1493jCallBooleanMethod(Obj, MethodID, Types, Params, Rbool) :-
 1494    jni_params_put(Params, Types, ParamBuf),
 1495    jni_func(39, Obj, MethodID, ParamBuf, Rbool).
 jCallByteMethod(+Obj:jref, +MethodID:methodId, +Types, +Params:list(datum), -Rbyte:byte)
 1501jCallByteMethod(Obj, MethodID, Types, Params, Rbyte) :-
 1502    jni_params_put(Params, Types, ParamBuf),
 1503    jni_func(42, Obj, MethodID, ParamBuf, Rbyte).
 jCallCharMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rchar:char)
 1509jCallCharMethod(Obj, MethodID, Types, Params, Rchar) :-
 1510    jni_params_put(Params, Types, ParamBuf),
 1511    jni_func(45, Obj, MethodID, ParamBuf, Rchar).
 jCallDoubleMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rdouble:double)
 1516jCallDoubleMethod(Obj, MethodID, Types, Params, Rdouble) :-
 1517    jni_params_put(Params, Types, ParamBuf),
 1518    jni_func(60, Obj, MethodID, ParamBuf, Rdouble).
 jCallFloatMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rfloat:float)
 1523jCallFloatMethod(Obj, MethodID, Types, Params, Rfloat) :-
 1524    jni_params_put(Params, Types, ParamBuf),
 1525    jni_func(57, Obj, MethodID, ParamBuf, Rfloat).
 jCallIntMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rint:int)
 1530jCallIntMethod(Obj, MethodID, Types, Params, Rint) :-
 1531    jni_params_put(Params, Types, ParamBuf),
 1532    jni_func(51, Obj, MethodID, ParamBuf, Rint).
 jCallLongMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rlong:long)
 1537jCallLongMethod(Obj, MethodID, Types, Params, Rlong) :-
 1538    jni_params_put(Params, Types, ParamBuf),
 1539    jni_func(54, Obj, MethodID, ParamBuf, Rlong).
 jCallObjectMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Robj:jref)
 1544jCallObjectMethod(Obj, MethodID, Types, Params, Robj) :-
 1545    jni_params_put(Params, Types, ParamBuf),
 1546    jni_func(36, Obj, MethodID, ParamBuf, Robj).
 jCallShortMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rshort:short)
 1551jCallShortMethod(Obj, MethodID, Types, Params, Rshort) :-
 1552    jni_params_put(Params, Types, ParamBuf),
 1553    jni_func(48, Obj, MethodID, ParamBuf, Rshort).
 jCallStaticBooleanMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rbool:boolean)
 1558jCallStaticBooleanMethod(Class, MethodID, Types, Params, Rbool) :-
 1559    jni_params_put(Params, Types, ParamBuf),
 1560    jni_func(119, Class, MethodID, ParamBuf, Rbool).
 jCallStaticByteMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rbyte:byte)
 1565jCallStaticByteMethod(Class, MethodID, Types, Params, Rbyte) :-
 1566    jni_params_put(Params, Types, ParamBuf),
 1567    jni_func(122, Class, MethodID, ParamBuf, Rbyte).
 jCallStaticCharMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rchar:char)
 1572jCallStaticCharMethod(Class, MethodID, Types, Params, Rchar) :-
 1573    jni_params_put(Params, Types, ParamBuf),
 1574    jni_func(125, Class, MethodID, ParamBuf, Rchar).
 jCallStaticDoubleMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rdouble:double)
 1579jCallStaticDoubleMethod(Class, MethodID, Types, Params, Rdouble) :-
 1580    jni_params_put(Params, Types, ParamBuf),
 1581    jni_func(140, Class, MethodID, ParamBuf, Rdouble).
 jCallStaticFloatMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rfloat:float)
 1586jCallStaticFloatMethod(Class, MethodID, Types, Params, Rfloat) :-
 1587    jni_params_put(Params, Types, ParamBuf),
 1588    jni_func(137, Class, MethodID, ParamBuf, Rfloat).
 jCallStaticIntMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rint:int)
 1593jCallStaticIntMethod(Class, MethodID, Types, Params, Rint) :-
 1594    jni_params_put(Params, Types, ParamBuf),
 1595    jni_func(131, Class, MethodID, ParamBuf, Rint).
 jCallStaticLongMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rlong:long)
 1600jCallStaticLongMethod(Class, MethodID, Types, Params, Rlong) :-
 1601    jni_params_put(Params, Types, ParamBuf),
 1602    jni_func(134, Class, MethodID, ParamBuf, Rlong).
 jCallStaticObjectMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Robj:jref)
 1607jCallStaticObjectMethod(Class, MethodID, Types, Params, Robj) :-
 1608    jni_params_put(Params, Types, ParamBuf),
 1609    jni_func(116, Class, MethodID, ParamBuf, Robj).
 jCallStaticShortMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rshort:short)
 1614jCallStaticShortMethod(Class, MethodID, Types, Params, Rshort) :-
 1615    jni_params_put(Params, Types, ParamBuf),
 1616    jni_func(128, Class, MethodID, ParamBuf, Rshort).
 jCallStaticVoidMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum))
 1621jCallStaticVoidMethod(Class, MethodID, Types, Params) :-
 1622    jni_params_put(Params, Types, ParamBuf),
 1623    jni_void(143, Class, MethodID, ParamBuf).
 jCallVoidMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum))
 1628jCallVoidMethod(Obj, MethodID, Types, Params) :-
 1629    jni_params_put(Params, Types, ParamBuf),
 1630    jni_void(63, Obj, MethodID, ParamBuf).
 jFindClass(+ClassName:findclassname, -Class:jref)
 1635jFindClass(ClassName, Class) :-
 1636    jni_func(6, ClassName, Class).
 jGetArrayLength(+Array:jref, -Size:int)
 1641jGetArrayLength(Array, Size) :-
 1642    jni_func(171, Array, Size).
 jGetBooleanArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:boolean_buf)
 1647jGetBooleanArrayRegion(Array, Start, Len, Buf) :-
 1648    jni_void(199, Array, Start, Len, Buf).
 jGetBooleanField(+Obj:jref, +FieldID:fieldId, -Rbool:boolean)
 1653jGetBooleanField(Obj, FieldID, Rbool) :-
 1654    jni_func(96, Obj, FieldID, Rbool).
 jGetByteArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:byte_buf)
 1659jGetByteArrayRegion(Array, Start, Len, Buf) :-
 1660    jni_void(200, Array, Start, Len, Buf).
 jGetByteField(+Obj:jref, +FieldID:fieldId, -Rbyte:byte)
 1665jGetByteField(Obj, FieldID, Rbyte) :-
 1666    jni_func(97, Obj, FieldID, Rbyte).
 jGetCharArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:char_buf)
 1671jGetCharArrayRegion(Array, Start, Len, Buf) :-
 1672    jni_void(201, Array, Start, Len, Buf).
 jGetCharField(+Obj:jref, +FieldID:fieldId, -Rchar:char)
 1677jGetCharField(Obj, FieldID, Rchar) :-
 1678    jni_func(98, Obj, FieldID, Rchar).
 jGetDoubleArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:double_buf)
 1683jGetDoubleArrayRegion(Array, Start, Len, Buf) :-
 1684    jni_void(206, Array, Start, Len, Buf).
 jGetDoubleField(+Obj:jref, +FieldID:fieldId, -Rdouble:double)
 1689jGetDoubleField(Obj, FieldID, Rdouble) :-
 1690    jni_func(103, Obj, FieldID, Rdouble).
 jGetFieldID(+Class:jref, +Name:fieldName, +Type:type, -FieldID:fieldId)
 1695jGetFieldID(Class, Name, Type, FieldID) :-
 1696    jpl_type_to_descriptor(Type, TD),
 1697    jni_func(94, Class, Name, TD, FieldID).
 jGetFloatArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:float_buf)
 1702jGetFloatArrayRegion(Array, Start, Len, Buf) :-
 1703    jni_void(205, Array, Start, Len, Buf).
 jGetFloatField(+Obj:jref, +FieldID:fieldId, -Rfloat:float)
 1708jGetFloatField(Obj, FieldID, Rfloat) :-
 1709    jni_func(102, Obj, FieldID, Rfloat).
 jGetIntArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:int_buf)
 1714jGetIntArrayRegion(Array, Start, Len, Buf) :-
 1715    jni_void(203, Array, Start, Len, Buf).
 jGetIntField(+Obj:jref, +FieldID:fieldId, -Rint:int)
 1720jGetIntField(Obj, FieldID, Rint) :-
 1721    jni_func(100, Obj, FieldID, Rint).
 jGetLongArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:long_buf)
 1726jGetLongArrayRegion(Array, Start, Len, Buf) :-
 1727    jni_void(204, Array, Start, Len, Buf).
 jGetLongField(+Obj:jref, +FieldID:fieldId, -Rlong:long)
 1732jGetLongField(Obj, FieldID, Rlong) :-
 1733    jni_func(101, Obj, FieldID, Rlong).
 jGetMethodID(+Class:jref, +Name:atom, +Type:type, -MethodID:methodId)
 1738jGetMethodID(Class, Name, Type, MethodID) :-
 1739    jpl_type_to_descriptor(Type, TD),
 1740    jni_func(33, Class, Name, TD, MethodID).
 jGetObjectArrayElement(+Array:jref, +Index:int, -Obj:jref)
 1745jGetObjectArrayElement(Array, Index, Obj) :-
 1746    jni_func(173, Array, Index, Obj).
 jGetObjectClass(+Object:jref, -Class:jref)
 1751jGetObjectClass(Object, Class) :-
 1752    jni_func(31, Object, Class).
 jGetObjectField(+Obj:jref, +FieldID:fieldId, -RObj:jref)
 1757jGetObjectField(Obj, FieldID, Robj) :-
 1758    jni_func(95, Obj, FieldID, Robj).
 jGetShortArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:short_buf)
 1763jGetShortArrayRegion(Array, Start, Len, Buf) :-
 1764    jni_void(202, Array, Start, Len, Buf).
 jGetShortField(+Obj:jref, +FieldID:fieldId, -Rshort:short)
 1769jGetShortField(Obj, FieldID, Rshort) :-
 1770    jni_func(99, Obj, FieldID, Rshort).
 jGetStaticBooleanField(+Class:jref, +FieldID:fieldId, -Rbool:boolean)
 1775jGetStaticBooleanField(Class, FieldID, Rbool) :-
 1776    jni_func(146, Class, FieldID, Rbool).
 jGetStaticByteField(+Class:jref, +FieldID:fieldId, -Rbyte:byte)
 1781jGetStaticByteField(Class, FieldID, Rbyte) :-
 1782    jni_func(147, Class, FieldID, Rbyte).
 jGetStaticCharField(+Class:jref, +FieldID:fieldId, -Rchar:char)
 1787jGetStaticCharField(Class, FieldID, Rchar) :-
 1788    jni_func(148, Class, FieldID, Rchar).
 jGetStaticDoubleField(+Class:jref, +FieldID:fieldId, -Rdouble:double)
 1793jGetStaticDoubleField(Class, FieldID, Rdouble) :-
 1794    jni_func(153, Class, FieldID, Rdouble).
 jGetStaticFieldID(+Class:jref, +Name:fieldName, +Type:type, -FieldID:fieldId)
 1799jGetStaticFieldID(Class, Name, Type, FieldID) :-
 1800    jpl_type_to_descriptor(Type, TD),               % cache this?
 1801    jni_func(144, Class, Name, TD, FieldID).
 jGetStaticFloatField(+Class:jref, +FieldID:fieldId, -Rfloat:float)
 1806jGetStaticFloatField(Class, FieldID, Rfloat) :-
 1807    jni_func(152, Class, FieldID, Rfloat).
 jGetStaticIntField(+Class:jref, +FieldID:fieldId, -Rint:int)
 1812jGetStaticIntField(Class, FieldID, Rint) :-
 1813    jni_func(150, Class, FieldID, Rint).
 jGetStaticLongField(+Class:jref, +FieldID:fieldId, -Rlong:long)
 1818jGetStaticLongField(Class, FieldID, Rlong) :-
 1819    jni_func(151, Class, FieldID, Rlong).
 jGetStaticMethodID(+Class:jref, +Name:methodName, +Type:type, -MethodID:methodId)
 1824jGetStaticMethodID(Class, Name, Type, MethodID) :-
 1825    jpl_type_to_descriptor(Type, TD),
 1826    jni_func(113, Class, Name, TD, MethodID).
 jGetStaticObjectField(+Class:jref, +FieldID:fieldId, -RObj:jref)
 1831jGetStaticObjectField(Class, FieldID, Robj) :-
 1832    jni_func(145, Class, FieldID, Robj).
 jGetStaticShortField(+Class:jref, +FieldID:fieldId, -Rshort:short)
 1837jGetStaticShortField(Class, FieldID, Rshort) :-
 1838    jni_func(149, Class, FieldID, Rshort).
 jGetSuperclass(+Class1:jref, -Class2:jref)
 1843jGetSuperclass(Class1, Class2) :-
 1844    jni_func(10, Class1, Class2).
 jIsAssignableFrom(+Class1:jref, +Class2:jref)
 1849jIsAssignableFrom(Class1, Class2) :-
 1850    jni_func(11, Class1, Class2, @(true)).
 jNewBooleanArray(+Length:int, -Array:jref)
 1855jNewBooleanArray(Length, Array) :-
 1856    jni_func(175, Length, Array).
 jNewByteArray(+Length:int, -Array:jref)
 1861jNewByteArray(Length, Array) :-
 1862    jni_func(176, Length, Array).
 jNewCharArray(+Length:int, -Array:jref)
 1867jNewCharArray(Length, Array) :-
 1868    jni_func(177, Length, Array).
 jNewDoubleArray(+Length:int, -Array:jref)
 1873jNewDoubleArray(Length, Array) :-
 1874    jni_func(182, Length, Array).
 jNewFloatArray(+Length:int, -Array:jref)
 1879jNewFloatArray(Length, Array) :-
 1880    jni_func(181, Length, Array).
 jNewIntArray(+Length:int, -Array:jref)
 1885jNewIntArray(Length, Array) :-
 1886    jni_func(179, Length, Array).
 jNewLongArray(+Length:int, -Array:jref)
 1891jNewLongArray(Length, Array) :-
 1892    jni_func(180, Length, Array).
 jNewObject(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Obj:jref)
 1897jNewObject(Class, MethodID, Types, Params, Obj) :-
 1898    jni_params_put(Params, Types, ParamBuf),
 1899    jni_func(30, Class, MethodID, ParamBuf, Obj).
 jNewObjectArray(+Len:int, +Class:jref, +InitVal:jref, -Array:jref)
 1904jNewObjectArray(Len, Class, InitVal, Array) :-
 1905    jni_func(172, Len, Class, InitVal, Array).
 jNewShortArray(+Length:int, -Array:jref)
 1910jNewShortArray(Length, Array) :-
 1911    jni_func(178, Length, Array).
 jSetBooleanArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:boolean_buf)
 1916jSetBooleanArrayRegion(Array, Start, Len, Buf) :-
 1917    jni_void(207, Array, Start, Len, Buf).
 jSetBooleanField(+Obj:jref, +FieldID:fieldId, +Rbool:boolean)
 1922jSetBooleanField(Obj, FieldID, Rbool) :-
 1923    jni_void(105, Obj, FieldID, Rbool).
 jSetByteArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:byte_buf)
 1928jSetByteArrayRegion(Array, Start, Len, Buf) :-
 1929    jni_void(208, Array, Start, Len, Buf).
 jSetByteField(+Obj:jref, +FieldID:fieldId, +Rbyte:byte)
 1934jSetByteField(Obj, FieldID, Rbyte) :-
 1935    jni_void(106, Obj, FieldID, Rbyte).
 jSetCharArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:char_buf)
 1940jSetCharArrayRegion(Array, Start, Len, Buf) :-
 1941    jni_void(209, Array, Start, Len, Buf).
 jSetCharField(+Obj:jref, +FieldID:fieldId, +Rchar:char)
 1946jSetCharField(Obj, FieldID, Rchar) :-
 1947    jni_void(107, Obj, FieldID, Rchar).
 jSetDoubleArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:double_buf)
 1952jSetDoubleArrayRegion(Array, Start, Len, Buf) :-
 1953    jni_void(214, Array, Start, Len, Buf).
 jSetDoubleField(+Obj:jref, +FieldID:fieldId, +Rdouble:double)
 1958jSetDoubleField(Obj, FieldID, Rdouble) :-
 1959    jni_void(112, Obj, FieldID, Rdouble).
 jSetFloatArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:float_buf)
 1964jSetFloatArrayRegion(Array, Start, Len, Buf) :-
 1965    jni_void(213, Array, Start, Len, Buf).
 jSetFloatField(+Obj:jref, +FieldID:fieldId, +Rfloat:float)
 1970jSetFloatField(Obj, FieldID, Rfloat) :-
 1971    jni_void(111, Obj, FieldID, Rfloat).
 jSetIntArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:int_buf)
 1976jSetIntArrayRegion(Array, Start, Len, Buf) :-
 1977    jni_void(211, Array, Start, Len, Buf).
 jSetIntField(+Obj:jref, +FieldID:fieldId, +Rint:int)
 1982jSetIntField(Obj, FieldID, Rint) :-
 1983    jni_void(109, Obj, FieldID, Rint).
 jSetLongArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:long_buf)
 1988jSetLongArrayRegion(Array, Start, Len, Buf) :-
 1989    jni_void(212, Array, Start, Len, Buf).
 jSetLongField(+Obj:jref, +FieldID:fieldId, +Rlong:long)
 1994jSetLongField(Obj, FieldID, Rlong) :-
 1995    jni_void(110, Obj, FieldID, Rlong).
 jSetObjectArrayElement(+Array:jref, +Index:int, +Obj:jref)
 2000jSetObjectArrayElement(Array, Index, Obj) :-
 2001    jni_void(174, Array, Index, Obj).
 jSetObjectField(+Obj:jref, +FieldID:fieldId, +RObj:jref)
 2006jSetObjectField(Obj, FieldID, Robj) :-
 2007    jni_void(104, Obj, FieldID, Robj).
 jSetShortArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:short_buf)
 2012jSetShortArrayRegion(Array, Start, Len, Buf) :-
 2013    jni_void(210, Array, Start, Len, Buf).
 jSetShortField(+Obj:jref, +FieldID:fieldId, +Rshort:short)
 2018jSetShortField(Obj, FieldID, Rshort) :-
 2019    jni_void(108, Obj, FieldID, Rshort).
 jSetStaticBooleanField(+Class:jref, +FieldID:fieldId, +Rbool:boolean)
 2024jSetStaticBooleanField(Class, FieldID, Rbool) :-
 2025    jni_void(155, Class, FieldID, Rbool).
 jSetStaticByteField(+Class:jref, +FieldID:fieldId, +Rbyte:byte)
 2030jSetStaticByteField(Class, FieldID, Rbyte) :-
 2031    jni_void(156, Class, FieldID, Rbyte).
 jSetStaticCharField(+Class:jref, +FieldID:fieldId, +Rchar:char)
 2036jSetStaticCharField(Class, FieldID, Rchar) :-
 2037    jni_void(157, Class, FieldID, Rchar).
 jSetStaticDoubleField(+Class:jref, +FieldID:fieldId, +Rdouble:double)
 2042jSetStaticDoubleField(Class, FieldID, Rdouble) :-
 2043    jni_void(162, Class, FieldID, Rdouble).
 jSetStaticFloatField(+Class:jref, +FieldID:fieldId, +Rfloat:float)
 2048jSetStaticFloatField(Class, FieldID, Rfloat) :-
 2049    jni_void(161, Class, FieldID, Rfloat).
 jSetStaticIntField(+Class:jref, +FieldID:fieldId, +Rint:int)
 2054jSetStaticIntField(Class, FieldID, Rint) :-
 2055    jni_void(159, Class, FieldID, Rint).
 jSetStaticLongField(+Class:jref, +FieldID:fieldId, +Rlong)
 2060jSetStaticLongField(Class, FieldID, Rlong) :-
 2061    jni_void(160, Class, FieldID, Rlong).
 jSetStaticObjectField(+Class:jref, +FieldID:fieldId, +Robj:jref)
 2066jSetStaticObjectField(Class, FieldID, Robj) :-
 2067    jni_void(154, Class, FieldID, Robj).
 jSetStaticShortField(+Class:jref, +FieldID:fieldId, +Rshort:short)
 2072jSetStaticShortField(Class, FieldID, Rshort) :-
 2073    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).
 2083jni_params_put(As, Ts, ParamBuf)     :-
 2084    jni_ensure_jvm,                     % in case e.g. NewStringUTF() is called
 2085    length(As, N),
 2086    jni_type_to_xput_code(jvalue, Xc), % Xc will be 15
 2087    jni_alloc_buffer(Xc, N, ParamBuf),
 2088    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

 2107jni_params_put_1([], _, [], _).
 2108jni_params_put_1([A|As], N, [Tjni|Ts], ParamBuf) :-     % type checking?
 2109    (   jni_type_to_xput_code(Tjni, Xc)
 2110    ->  (   A = {Term}                                  % a quoted general term?
 2111        ->  jni_term_to_jref(Term, Ax)                  % convert it to a @(Tag) ref to a new Term instance
 2112        ;   A = Ax
 2113        ),
 2114        jni_param_put(N, Xc, Ax, ParamBuf)              % foreign
 2115    ;   fail                                            % oughta raise an exception?
 2116    ),
 2117    N2 is N+1,
 2118    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)

 2128jni_type_to_xput_code(boolean,      1).     % JNI_XPUT_BOOLEAN
 2129jni_type_to_xput_code(byte,         2).     % JNI_XPUT_BYTE
 2130jni_type_to_xput_code(char,         3).     % JNI_XPUT_CHAR
 2131jni_type_to_xput_code(short,        4).     % JNI_XPUT_SHORT
 2132jni_type_to_xput_code(int,          5).     % JNI_XPUT_INT
 2133jni_type_to_xput_code(long,         6).     % JNI_XPUT_LONG
 2134jni_type_to_xput_code(float,        7).     % JNI_XPUT_FLOAT
 2135jni_type_to_xput_code(double,       8).     % JNI_XPUT_DOUBLE
 2136jni_type_to_xput_code(class(_,_),   12).    % JNI_XPUT_REF
 2137jni_type_to_xput_code(array(_),     12).    % JNI_XPUT_REF
 2138jni_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?
 2145jpl_class_to_constructor_array(Cx, Ma) :-
 2146    jpl_classname_to_class('java.lang.Class', CC),      % cacheable?
 2147    jGetMethodID( CC, getConstructors, method([],array(class([java,lang,reflect],['Constructor']))), MID), % cacheable?
 2148    jCallObjectMethod(Cx, MID, [], [], Ma).
 jpl_class_to_constructors(+Class:jref, -Methods:list(jref))
 2153jpl_class_to_constructors(Cx, Ms) :-
 2154    jpl_class_to_constructor_array(Cx, Ma),
 2155    jpl_object_array_to_list(Ma, Ms).
 jpl_class_to_field_array(+Class:jref, -FieldArray:jref)
 2160jpl_class_to_field_array(Cx, Fa) :-
 2161    jpl_classname_to_class('java.lang.Class', CC),      % cacheable?
 2162    jGetMethodID(CC, getFields, method([],array(class([java,lang,reflect],['Field']))), MID),  % cacheable?
 2163    jCallObjectMethod(Cx, MID, [], [], Fa).
 jpl_class_to_fields(+Class:jref, -Fields:list(jref))
NB do this in Java (ditto for methods)?
 2170jpl_class_to_fields(C, Fs) :-
 2171    jpl_class_to_field_array(C, Fa),
 2172    jpl_object_array_to_list(Fa, Fs).
 jpl_class_to_method_array(+Class:jref, -MethodArray:jref)
NB migrate into foreign code for efficiency?
 2179jpl_class_to_method_array(Cx, Ma) :-
 2180    jpl_classname_to_class('java.lang.Class', CC),      % cacheable?
 2181    jGetMethodID(CC, getMethods, method([],array(class([java,lang,reflect],['Method']))), MID),  % cacheable?
 2182    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)?

 2191jpl_class_to_methods(Cx, Ms) :-
 2192    jpl_class_to_method_array(Cx, Ma),
 2193    jpl_object_array_to_list(Ma, Ms).
 jpl_constructor_to_modifiers(+Method, -Modifiers)
NB migrate into foreign code for efficiency?
 2200jpl_constructor_to_modifiers(X, Ms) :-
 2201    jpl_classname_to_class('java.lang.reflect.Constructor', Cx),   % cached?
 2202    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>'.
 2210jpl_constructor_to_name(_X, '<init>').
 jpl_constructor_to_parameter_types(+Method:jref, -ParameterTypes:list(type))
NB migrate to foreign code for efficiency?
 2217jpl_constructor_to_parameter_types(X, Tfps) :-
 2218    jpl_classname_to_class('java.lang.reflect.Constructor', Cx),   % cached?
 2219    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'.
 2227jpl_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.
 2234jpl_field_spec(T, I, N, Mods, MID, Tf) :-
 2235    (   jpl_field_spec_is_cached(T)
 2236    ->  jpl_field_spec_cache(T, I, N, Mods, MID, Tf)
 2237    ;   jpl_type_to_class(T, C),
 2238        jpl_class_to_fields(C, Fs),
 2239        (   T = array(_BaseType)    % regardless of base type...
 2240        ->  Tci = array(_)          % ...the "cache index" type is this
 2241        ;   Tci = T
 2242        ),
 2243        jpl_field_spec_1(C, Tci, Fs),
 2244        jpl_assert(jpl_field_spec_is_cached(Tci)),
 2245        jpl_field_spec_cache(Tci, I, N, Mods, MID, Tf)
 2246    ).
 2247
 2248
 2249jpl_field_spec_1(C, Tci, Fs) :-
 2250    (   nth1(I, Fs, F),
 2251        jpl_field_to_name(F, N),
 2252        jpl_field_to_modifiers(F, Mods),
 2253        jpl_field_to_type(F, Tf),
 2254        (   member(static, Mods)
 2255        ->  jGetStaticFieldID(C, N, Tf, MID)
 2256        ;   jGetFieldID(C, N, Tf, MID)
 2257        ),
 2258        jpl_assert(jpl_field_spec_cache(Tci,I,N,Mods,MID,Tf)),
 2259        fail
 2260    ;   true
 2261    ).
 2262
 2263
 2264:- dynamic jpl_field_spec_cache/6.      % document this...
 2265
 2266
 2267:- dynamic jpl_field_spec_is_cached/1.  % document this...
 jpl_field_to_modifiers(+Field:jref, -Modifiers:ordset(modifier))
 2272jpl_field_to_modifiers(F, Ms) :-
 2273    jpl_classname_to_class('java.lang.reflect.Field', Cf),
 2274    jpl_method_to_modifiers_1(F, Cf, Ms).
 jpl_field_to_name(+Field:jref, -Name:atom)
 2279jpl_field_to_name(F, N) :-
 2280    jpl_classname_to_class('java.lang.reflect.Field', Cf),
 2281    jpl_member_to_name_1(F, Cf, N).
 jpl_field_to_type(+Field:jref, -Type:type)
 2286jpl_field_to_type(F, Tf) :-
 2287    jpl_classname_to_class('java.lang.reflect.Field', Cf),
 2288    jGetMethodID(Cf, getType, method([],class([java,lang],['Class'])), MID),
 2289    jCallObjectMethod(F, MID, [], [], Cr),
 2290    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.
 2298jpl_method_spec(T, I, N, A, Mods, MID, Tr, Tfps) :-
 2299    (   jpl_method_spec_is_cached(T)
 2300    ->  jpl_method_spec_cache(T, I, N, A, Mods, MID, Tr, Tfps)
 2301    ;   jpl_type_to_class(T, C),
 2302        jpl_class_to_constructors(C, Xs),
 2303        jpl_class_to_methods(C, Ms),
 2304        (   T = array(_BaseType)    % regardless of base type...
 2305        ->  Tci = array(_)          % ...the "cache index" type is this
 2306        ;   Tci = T
 2307        ),
 2308        jpl_method_spec_1(C, Tci, Xs, Ms),
 2309        jpl_assert(jpl_method_spec_is_cached(Tci)),
 2310        jpl_method_spec_cache(Tci, I, N, A, Mods, MID, Tr, Tfps)
 2311    ).
 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.
 2318jpl_method_spec_1(C, Tci, Xs, Ms) :-
 2319    (   (   nth1(I, Xs, X),     % generate constructors, numbered from 1
 2320            jpl_constructor_to_name(X, N),
 2321            jpl_constructor_to_modifiers(X, Mods),
 2322            jpl_constructor_to_return_type(X, Tr),
 2323            jpl_constructor_to_parameter_types(X, Tfps)
 2324        ;   length(Xs, J0),
 2325            nth1(J, Ms, M),     % generate members, continuing numbering
 2326            I is J0+J,
 2327            jpl_method_to_name(M, N),
 2328            jpl_method_to_modifiers(M, Mods),
 2329            jpl_method_to_return_type(M, Tr),
 2330            jpl_method_to_parameter_types(M, Tfps)
 2331        ),
 2332        length(Tfps, A), % arity
 2333        (   member(static, Mods)
 2334        ->  jGetStaticMethodID(C, N, method(Tfps,Tr), MID)
 2335        ;   jGetMethodID(C, N, method(Tfps,Tr), MID)
 2336        ),
 2337        jpl_assert(jpl_method_spec_cache(Tci,I,N,A,Mods,MID,Tr,Tfps)),
 2338        fail
 2339    ;   true
 2340    ).
 2341
 2342
 2343:- dynamic jpl_method_spec_cache/8. 2344
 2345
 2346:- dynamic jpl_method_spec_is_cached/1.
 jpl_method_to_modifiers(+Method:jref, -ModifierSet:ordset(modifier))
 2351jpl_method_to_modifiers(M, Ms) :-
 2352    jpl_classname_to_class('java.lang.reflect.Method', Cm),
 2353    jpl_method_to_modifiers_1(M, Cm, Ms).
 jpl_method_to_modifiers_1(+Method:jref, +ConstructorClass:jref, -ModifierSet:ordset(modifier))
 2358jpl_method_to_modifiers_1(XM, Cxm, Ms) :-
 2359    jGetMethodID(Cxm, getModifiers, method([],int), MID),
 2360    jCallIntMethod(XM, MID, [], [], I),
 2361    jpl_modifier_int_to_modifiers(I, Ms).
 jpl_method_to_name(+Method:jref, -Name:atom)
 2366jpl_method_to_name(M, N) :-
 2367    jpl_classname_to_class('java.lang.reflect.Method', CM),
 2368    jpl_member_to_name_1(M, CM, N).
 jpl_member_to_name_1(+Member:jref, +CM:jref, -Name:atom)
 2373jpl_member_to_name_1(M, CM, N) :-
 2374    jGetMethodID(CM, getName, method([],class([java,lang],['String'])), MID),
 2375    jCallObjectMethod(M, MID, [], [], N).
 jpl_method_to_parameter_types(+Method:jref, -Types:list(type))
 2380jpl_method_to_parameter_types(M, Tfps) :-
 2381    jpl_classname_to_class('java.lang.reflect.Method', Cm),
 2382    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]
 2389jpl_method_to_parameter_types_1(XM, Cxm, Tfps) :-
 2390    jGetMethodID(Cxm, getParameterTypes, method([],array(class([java,lang],['Class']))), MID),
 2391    jCallObjectMethod(XM, MID, [], [], Atp),
 2392    jpl_object_array_to_list(Atp, Ctps),
 2393    jpl_classes_to_types(Ctps, Tfps).
 jpl_method_to_return_type(+Method:jref, -Type:type)
 2398jpl_method_to_return_type(M, Tr) :-
 2399    jpl_classname_to_class('java.lang.reflect.Method', Cm),
 2400    jGetMethodID(Cm, getReturnType, method([],class([java,lang],['Class'])), MID),
 2401    jCallObjectMethod(M, MID, [], [], Cr),
 2402    jpl_class_to_type(Cr, Tr).
 2403
 2404
 2405jpl_modifier_bit(public,        0x001).
 2406jpl_modifier_bit(private,       0x002).
 2407jpl_modifier_bit(protected,     0x004).
 2408jpl_modifier_bit(static,        0x008).
 2409jpl_modifier_bit(final,         0x010).
 2410jpl_modifier_bit(synchronized,  0x020).
 2411jpl_modifier_bit(volatile,      0x040).
 2412jpl_modifier_bit(transient,     0x080).
 2413jpl_modifier_bit(native,        0x100).
 2414jpl_modifier_bit(interface,     0x200).
 2415jpl_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]
 2424jpl_modifier_int_to_modifiers(I, Ms) :-
 2425    setof(
 2426        M,                                  %  should use e.g. set_of_all/3
 2427        B^( jpl_modifier_bit(M, B),
 2428            (B /\ I) =\= 0
 2429        ),
 2430        Ms
 2431    ).
 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

 2445jpl_cache_type_of_ref(T, Ref) :-
 2446    (   jpl_assert_policy(jpl_iref_type_cache(_,_), no)
 2447    ->  true
 2448    ;   \+ ground(T)                            % shouldn't happen (implementation error)
 2449    ->  write('[jpl_cache_type_of_ref/2: arg 1 is not ground]'), nl,    % oughta throw an exception
 2450        fail
 2451    ;   Ref == @(null)                          % a null ref? (this is valid)
 2452    ->  true                                    % silently ignore it
 2453    ;   (   jpl_iref_type_cache(Ref, TC)        % we expect TC == T
 2454        ->  (   T == TC
 2455            ->  true
 2456            ; % write('[JPL: found obsolete tag-type lemma...]'), nl,   % or keep statistics? (why?)
 2457                retractall(jpl_iref_type_cache(Ref,_)),
 2458                jpl_assert(jpl_iref_type_cache(Ref,T))
 2459            )
 2460        ;   jpl_assert(jpl_iref_type_cache(Ref,T))
 2461        )
 2462    ).
 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)

 2473:- 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)
 2484jpl_class_to_ancestor_classes(C, Cas) :-
 2485    (   jpl_class_to_super_class(C, Ca)
 2486    ->  Cas = [Ca|Cas2],
 2487        jpl_class_to_ancestor_classes(Ca, Cas2)
 2488    ;   Cas = []
 2489    ).
 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)

 2503jpl_class_to_classname(C, CN) :-
 2504    jpl_call(C, getName, [], CN).
 jpl_class_to_raw_classname(+Class:jref, -ClassName:rawName)
Hhmm, I forget exactly what a "raw" classname is.
 2511jpl_class_to_raw_classname(Cobj, CN) :-
 2512    jpl_classname_to_class('java.lang.Class', CC),      % cached?
 2513    jGetMethodID(CC, getName, method([],class([java,lang],['String'])), MIDgetName),
 2514    jCallObjectMethod(Cobj, MIDgetName, [], [], S),
 2515    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

 2524jpl_class_to_raw_classname_chars(Cobj, CsCN) :-
 2525    jpl_class_to_raw_classname(Cobj, CN),
 2526    atom_codes(CN, CsCN).
 2527
 2528
 2529jpl_class_to_super_class(C, Cx) :-
 2530    jGetSuperclass(C, Cx),
 2531    Cx \== @(null),         % as returned when C is java.lang.Object, i.e. no superclass
 2532    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' (?!)

 2544jpl_class_to_type(Ref, Type) :-
 2545    (   jpl_class_tag_type_cache(Ref, Tx)
 2546    ->  true
 2547    ;   jpl_class_to_raw_classname_chars(Ref, Cs),   % uncached
 2548        jpl_classname_chars_to_type(Cs, Tr),
 2549        jpl_type_to_canonical_type(Tr, Tx),             % map e.g. class([],[byte]) -> byte
 2550        jpl_assert(jpl_class_tag_type_cache(Ref,Tx))
 2551    ->  true    % the elseif goal should be determinate, but just in case...
 2552    ),
 2553    Type = Tx.
 2554
 2555
 2556jpl_classes_to_types([], []).
 2557jpl_classes_to_types([C|Cs], [T|Ts]) :-
 2558    jpl_class_to_type(C, T),
 2559    jpl_classes_to_types(Cs, Ts).
 2560
 2561
 2562jpl_classname_chars_to_type(Cs, Type) :-
 2563    (   phrase(jpl_type_classname_1(Type), Cs)
 2564    ->  true
 2565    ).
 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.

 2576jpl_classname_to_class(N, C) :-
 2577    jpl_classname_to_type(N, T),    % cached
 2578    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?

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

NB may denote a class which cannot be found.

 2607:- 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
 2622jpl_datum_to_type(D, T) :-
 2623    (   jpl_value_to_type(D, T)
 2624    ->  true
 2625    ;   jpl_ref_to_type(D, T)
 2626    ->  true
 2627    ;   nonvar(D),
 2628        D = {Term}
 2629    ->  (   cyclic_term(Term)
 2630        ->  throw(error(type_error(acyclic,Term),context(jpl_datum_to_type/2,'must be acyclic')))
 2631        ;   atom(Term)
 2632        ->  T = class([org,jpl7],['Atom'])
 2633        ;   integer(Term)
 2634        ->  T = class([org,jpl7],['Integer'])
 2635        ;   float(Term)
 2636        ->  T = class([org,jpl7],['Float'])
 2637        ;   var(Term)
 2638        ->  T = class([org,jpl7],['Variable'])
 2639        ;   T = class([org,jpl7],['Compound'])
 2640        )
 2641    ).
 2642
 2643
 2644jpl_datums_to_most_specific_common_ancestor_type([D], T) :-
 2645    jpl_datum_to_type(D, T).
 2646jpl_datums_to_most_specific_common_ancestor_type([D1,D2|Ds], T0) :-
 2647    jpl_datum_to_type(D1, T1),
 2648    jpl_type_to_ancestor_types(T1, Ts1),
 2649    jpl_datums_to_most_specific_common_ancestor_type_1([D2|Ds], [T1|Ts1], [T0|_]).
 2650
 2651
 2652jpl_datums_to_most_specific_common_ancestor_type_1([], Ts, Ts).
 2653jpl_datums_to_most_specific_common_ancestor_type_1([D|Ds], Ts1, Ts0) :-
 2654    jpl_datum_to_type(D, Tx),
 2655    jpl_lineage_types_type_to_common_lineage_types(Ts1, Tx, Ts2),
 2656    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).
 2667jpl_datums_to_types([], []).
 2668jpl_datums_to_types([D|Ds], [T|Ts]) :-
 2669    jpl_datum_to_type(D, T),
 2670    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.
 2677jpl_ground_is_type(X) :-
 2678    jpl_primitive_type(X),
 2679    !.
 2680jpl_ground_is_type(array(X)) :-
 2681    jpl_ground_is_type(X).
 2682jpl_ground_is_type(class(_,_)).
 2683jpl_ground_is_type(method(_,_)).
 2684
 2685
 2686:- dynamic jpl_iref_type_cache/2. 2687
 2688
 2689jpl_lineage_types_type_to_common_lineage_types(Ts, Tx, Ts0) :-
 2690    (   append(_, [Tx|Ts2], Ts)
 2691    ->  [Tx|Ts2] = Ts0
 2692    ;   jpl_type_to_super_type(Tx, Tx2)
 2693    ->  jpl_lineage_types_type_to_common_lineage_types(Ts, Tx2, Ts0)
 2694    ).
 2695
 2696
 2697jpl_non_var_is_object_type(class(_,_)).
 2698
 2699jpl_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.
 2707jpl_object_array_to_list(A, Vs) :-
 2708    jpl_array_to_length(A, N),
 2709    jpl_object_array_to_list_1(A, 0, N, Vs).
 jpl_object_array_to_list_1(+A, +I, +N, -Xs)
 2714jpl_object_array_to_list_1(A, I, N, Xs) :-
 2715    (   I == N
 2716    ->  Xs = []
 2717    ;   jGetObjectArrayElement(A, I, X),
 2718        Xs = [X|Xs2],
 2719        J is I+1,
 2720        jpl_object_array_to_list_1(A, J, N, Xs2)
 2721    ).
 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?

 2733jpl_object_to_class(Obj, C) :-
 2734    jpl_is_object(Obj),
 2735    jGetObjectClass(Obj, C),
 2736    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.

 2746jpl_object_to_type(Ref, Type) :-
 2747    jpl_is_object(Ref),
 2748    (   jpl_iref_type_cache(Ref, T)
 2749    ->  true                                % T is Tag's type
 2750    ;   jpl_object_to_class(Ref, Cobj),     % else get ref to class obj
 2751        jpl_class_to_type(Cobj, T),         % get type of class it denotes
 2752        jpl_assert(jpl_iref_type_cache(Ref,T))
 2753    ),
 2754    Type = T.
 2755
 2756
 2757jpl_object_type_to_super_type(T, Tx) :-
 2758    (   (   T = class(_,_)
 2759        ;   T = array(_)
 2760        )
 2761    ->  jpl_type_to_class(T, C),
 2762        jpl_class_to_super_class(C, Cx),
 2763        Cx \== @(null),
 2764        jpl_class_to_type(Cx, Tx)
 2765    ).
 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)

 2776jpl_primitive_buffer_to_array(T, Xc, Bp, I, Size, [Vc|Vcs]) :-
 2777    jni_fetch_buffer_value(Bp, I, Vc, Xc),
 2778    Ix is I+1,
 2779    (   Ix < Size
 2780    ->  jpl_primitive_buffer_to_array(T, Xc, Bp, Ix, Size, Vcs)
 2781    ;   Vcs = []
 2782    ).
 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].
 2794jpl_primitive_type(boolean).
 2795jpl_primitive_type(char).
 2796jpl_primitive_type(byte).
 2797jpl_primitive_type(short).
 2798jpl_primitive_type(int).
 2799jpl_primitive_type(long).
 2800jpl_primitive_type(float).
 2801jpl_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).
 2810jpl_primitive_type_default_value(boolean, @(false)).
 2811jpl_primitive_type_default_value(char,    0).
 2812jpl_primitive_type_default_value(byte,    0).
 2813jpl_primitive_type_default_value(short,   0).
 2814jpl_primitive_type_default_value(int,     0).
 2815jpl_primitive_type_default_value(long,    0).
 2816jpl_primitive_type_default_value(float,   0.0).
 2817jpl_primitive_type_default_value(double,  0.0).
 2818
 2819
 2820jpl_primitive_type_super_type(T, Tx) :-
 2821    (   jpl_type_fits_type_direct_prim(T, Tx)
 2822    ;   jpl_type_fits_type_direct_xtra(T, Tx)
 2823    ).
 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)

 2836jpl_primitive_type_term_to_value(Type, Term, Val) :-
 2837    (   jpl_primitive_type_term_to_value_1(Type, Term, Val)
 2838    ->  true
 2839    ).
 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.

 2848jpl_primitive_type_term_to_value_1(boolean, @(false), @(false)).
 2849jpl_primitive_type_term_to_value_1(boolean, @(true), @(true)).
 2850jpl_primitive_type_term_to_value_1(char, I, I) :-
 2851    integer(I),
 2852    I >= 0,
 2853    I =< 65535.         %  (2**16)-1.
 2854jpl_primitive_type_term_to_value_1(byte, I, I) :-
 2855    integer(I),
 2856    I >= 128,           % -(2**7)
 2857    I =< 127.           %  (2**7)-1
 2858jpl_primitive_type_term_to_value_1(short, I, I) :-
 2859    integer(I),
 2860    I >= -32768,        % -(2**15)
 2861    I =<  32767.        %  (2**15)-1
 2862jpl_primitive_type_term_to_value_1(int, I, I) :-
 2863    integer(I),
 2864    I >= -2147483648,   % -(2**31)
 2865    I =<  2147483647.   %  (2**31)-1
 2866jpl_primitive_type_term_to_value_1(long, I, I) :-
 2867    integer(I),
 2868    I >= -9223372036854775808,  % -(2**63)
 2869    I =<  9223372036854775807.  %  (2**63)-1
 2870jpl_primitive_type_term_to_value_1(float, V, F) :-
 2871    (   integer(V)
 2872    ->  F is float(V)
 2873    ;   float(V)
 2874    ->  F = V
 2875    ).
 2876jpl_primitive_type_term_to_value_1(double, V, F) :-
 2877    (   integer(V)
 2878    ->  F is float(V)
 2879    ;   float(V)
 2880    ->  F = V
 2881    ).
 2882
 2883
 2884jpl_primitive_type_to_ancestor_types(T, Ts) :-
 2885    (   jpl_primitive_type_super_type(T, Ta)
 2886    ->  Ts = [Ta|Tas],
 2887        jpl_primitive_type_to_ancestor_types(Ta, Tas)
 2888    ;   Ts = []
 2889    ).
 2890
 2891
 2892jpl_primitive_type_to_super_type(T, Tx) :-
 2893    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.

 2902jpl_ref_to_type(Ref, T) :-
 2903    (   Ref == @(null)
 2904    ->  T = null
 2905    ;   Ref == @(void)
 2906    ->  T = void
 2907    ;   jpl_object_to_type(Ref, T)
 2908    ).
 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

 2918jpl_tag_to_type(Tag, Type) :-
 2919    jni_tag_to_iref(Tag, Iref),
 2920    (   jpl_iref_type_cache(Iref, T)
 2921    ->  true                                % T is Tag's type
 2922    ;   jpl_object_to_class(@(Tag), Cobj), % else get ref to class obj
 2923        jpl_class_to_type(Cobj, T),         % get type of class it denotes
 2924        jpl_assert(jpl_iref_type_cache(Iref,T))
 2925    ),
 2926    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.

 2935jpl_type_fits_type(Tx, Ty) :-
 2936    (   jpl_type_fits_type_1(Tx, Ty)
 2937    ->  true
 2938    ).
 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
 2945jpl_type_fits_type_1(T, T).
 2946jpl_type_fits_type_1(class(Ps1,Cs1), class(Ps2,Cs2)) :-
 2947    jpl_type_to_class(class(Ps1,Cs1), C1),
 2948    jpl_type_to_class(class(Ps2,Cs2), C2),
 2949    jIsAssignableFrom(C1, C2).
 2950jpl_type_fits_type_1(array(T1), class(Ps2,Cs2)) :-
 2951    jpl_type_to_class(array(T1), C1),
 2952    jpl_type_to_class(class(Ps2,Cs2), C2),
 2953    jIsAssignableFrom(C1, C2).
 2954jpl_type_fits_type_1(array(T1), array(T2)) :-
 2955    jpl_type_to_class(array(T1), C1),
 2956    jpl_type_to_class(array(T2), C2),
 2957    jIsAssignableFrom(C1, C2).
 2958jpl_type_fits_type_1(null, class(_,_)).
 2959jpl_type_fits_type_1(null, array(_)).
 2960jpl_type_fits_type_1(T1, T2) :-
 2961    jpl_type_fits_type_xprim(T1, T2).
 2962
 2963
 2964jpl_type_fits_type_direct_prim(float, double).
 2965jpl_type_fits_type_direct_prim(long,  float).
 2966jpl_type_fits_type_direct_prim(int,   long).
 2967jpl_type_fits_type_direct_prim(char,  int).
 2968jpl_type_fits_type_direct_prim(short, int).
 2969jpl_type_fits_type_direct_prim(byte,  short).
 2970
 2971
 2972jpl_type_fits_type_direct_xprim(Tp, Tq) :-
 2973    jpl_type_fits_type_direct_prim(Tp, Tq).
 2974jpl_type_fits_type_direct_xprim(Tp, Tq) :-
 2975    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
 2983jpl_type_fits_type_direct_xtra(char_int,   int).    % char_int is a direct subtype of int
 2984jpl_type_fits_type_direct_xtra(char_int,   char).   % etc.
 2985jpl_type_fits_type_direct_xtra(char_short, short).
 2986jpl_type_fits_type_direct_xtra(char_short, char).
 2987jpl_type_fits_type_direct_xtra(char_byte,  byte).
 2988jpl_type_fits_type_direct_xtra(char_byte,  char).
 2989jpl_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
 2996jpl_type_fits_type_xprim(Tp, T) :-
 2997    jpl_type_fits_type_direct_xprim(Tp, Tq),
 2998    (   Tq = T
 2999    ;   jpl_type_fits_type_xprim(Tq, T)
 3000    ).
 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.
 3008jpl_type_to_ancestor_types(T, Tas) :-
 3009    (   (   T = class(_,_)
 3010        ;   T = array(_)
 3011        )
 3012    ->  jpl_type_to_class(T, C),
 3013        jpl_class_to_ancestor_classes(C, Cas),
 3014        jpl_classes_to_types(Cas, Tas)
 3015    ;   jpl_primitive_type_to_ancestor_types(T, Tas)
 3016    ->  true
 3017    ).
 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.
 3032jpl_type_to_canonical_type(array(T), array(Tc)) :-
 3033    !,
 3034    jpl_type_to_canonical_type(T, Tc).
 3035jpl_type_to_canonical_type(class([],[void]), void) :-
 3036    !.
 3037jpl_type_to_canonical_type(class([],[N]), N) :-
 3038    jpl_primitive_type(N),
 3039    !.
 3040jpl_type_to_canonical_type(class(Ps,Cs), class(Ps,Cs)) :-
 3041    !.
 3042jpl_type_to_canonical_type(void, void) :-
 3043    !.
 3044jpl_type_to_canonical_type(P, P) :-
 3045    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.

 3054jpl_type_to_class(T, RefA) :-
 3055    (   ground(T)
 3056	->  (   jpl_class_tag_type_cache(RefB, T)
 3057	    ->  true
 3058	    ;   (   jpl_type_to_findclassname(T, FCN)   % peculiar syntax for FindClass()
 3059	        ->  jFindClass(FCN, RefB),       % which caches type of RefB
 3060	            jpl_cache_type_of_ref(class([java,lang],['Class']), RefB)    % 9/Nov/2004 bugfix (?)
 3061	        ),
 3062	        jpl_assert(jpl_class_tag_type_cache(RefB,T))
 3063	    ),
 3064	    RefA = RefB
 3065    ;   throw(error(instantiation_error,context(jpl_type_to_class/2,'1st arg must be bound to a JPL type')))
 3066    ).
 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
 3089jpl_type_to_nicename(T, NN) :-
 3090    (   jpl_primitive_type(T)
 3091    ->  NN = T
 3092    ;   (   phrase(jpl_type_classname_1(T), Cs)
 3093        ->  atom_codes(CNx, Cs),                                % green commit to first solution
 3094            NN = CNx
 3095        )
 3096    ).
 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
 3108jpl_type_to_classname(T, CN) :-
 3109    (   phrase(jpl_type_classname_1(T), Cs)
 3110    ->  atom_codes(CNx, Cs),                                % green commit to first solution
 3111        CN = CNx
 3112    ).
 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?)

 3129jpl_type_to_descriptor(T, D) :-
 3130    (   phrase(jpl_type_descriptor_1(T), Cs)
 3131    ->  atom_codes(Dx, Cs),
 3132        D = Dx
 3133    ).
 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'.
 3147jpl_type_to_findclassname(T, FCN) :-
 3148    (   phrase(jpl_type_findclassname(T), Cs)
 3149    ->  atom_codes(FCNx, Cs),
 3150        FCN = FCNx
 3151    ).
 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.

 3162jpl_type_to_super_type(T, Tx) :-
 3163    (   jpl_object_type_to_super_type(T, Tx)
 3164    ->  true
 3165    ;   jpl_primitive_type_to_super_type(T, Tx)
 3166    ->  true
 3167    ).
 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

 3186jpl_type_to_preferred_concrete_type(T, Tc) :-
 3187    (   jpl_type_to_preferred_concrete_type_1(T, TcX)
 3188    ->  Tc = TcX
 3189    ).
 3190
 3191
 3192jpl_type_to_preferred_concrete_type_1(char_int, int).
 3193jpl_type_to_preferred_concrete_type_1(char_short, short).
 3194jpl_type_to_preferred_concrete_type_1(char_byte, byte).
 3195jpl_type_to_preferred_concrete_type_1(array(T), array(Tc)) :-
 3196    jpl_type_to_preferred_concrete_type_1(T, Tc).
 3197jpl_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.

 3206jpl_types_fit_type([], _).
 3207jpl_types_fit_type([T1|T1s], T2) :-
 3208    jpl_type_fits_type(T1, T2),
 3209    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.
 3216jpl_types_fit_types([], []).
 3217jpl_types_fit_types([T1|T1s], [T2|T2s]) :-
 3218    jpl_type_fits_type(T1, T2),
 3219    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.

 3230jpl_value_to_type(V, T) :-
 3231    ground(V),                          % critically assumed by jpl_value_to_type_1/2
 3232    (   jpl_value_to_type_1(V, Tv)      % 2nd arg must be unbound
 3233    ->  T = Tv
 3234    ).
 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.

 3251jpl_value_to_type_1(@(false), boolean) :- !.
 3252jpl_value_to_type_1(@(true), boolean) :- !.
 3253jpl_value_to_type_1(A, class([java,lang],['String'])) :-   % yes it's a "value"
 3254    atom(A),
 3255    !.
 3256jpl_value_to_type_1(I, T) :-
 3257    integer(I),
 3258    !,
 3259    (   I >= 0
 3260    ->  (   I  < 128                 ->  T = char_byte
 3261        ;   I  < 32768               ->  T = char_short
 3262        ;   I  < 65536               ->  T = char_int
 3263        ;   I  < 2147483648          ->  T = int
 3264        ;   I =< 9223372036854775807 ->  T = long
 3265        ;   T = overlong
 3266        )
 3267    ;   I >= -128                 ->  T = byte
 3268    ;   I >= -32768               ->  T = short
 3269    ;   I >= -2147483648          ->  T = int
 3270    ;   I >= -9223372036854775808 ->  T = long
 3271    ;   T = overlong
 3272    ).
 3273jpl_value_to_type_1(F, float) :-
 3274    float(F).
 jpl_is_class(@Term)
True if Term is a JPL reference to an instance of java.lang.Class.
 3281jpl_is_class(X) :-
 3282    jpl_is_object(X),
 3283    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'.
 3290jpl_is_false(X) :-
 3291    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.

 3304jpl_is_fieldID(jfieldID(X)) :-
 3305    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.

 3318jpl_is_methodID(jmethodID(X)) :-   % NB a var arg may get bound...
 3319    integer(X).
 jpl_is_null(@Term)
True if Term is @(null), the JPL representation of Java's 'null' reference.
 3326jpl_is_null(X) :-
 3327    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.

 3336jpl_is_object(X) :-
 3337	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.
 3344jpl_is_object_type(T) :-
 3345    \+ var(T),
 3346    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.
 3355jpl_is_ref(Term) :-
 3356    (	jpl_is_object(Term)
 3357    ->	true
 3358    ;	jpl_is_null(Term)
 3359    ->	true
 3360    ).
 jpl_is_true(@Term)
True if Term is @(true), the JPL representation of the Java boolean value 'true'.
 3368jpl_is_true(X) :-
 3369    X == @(true).
 jpl_is_type(@Term)
True if Term is a well-formed JPL type structure.
 3375jpl_is_type(X) :-
 3376    ground(X),
 3377    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.

 3388jpl_is_void(X) :-
 3389    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
 3398jpl_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
 3406jpl_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
 3415jpl_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
 3425jpl_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)
    ).
 3442jpl_array_to_length(A, N) :-
 3443    (   jpl_ref_to_type(A, array(_))    % can this be done cheaper e.g. in foreign code?
 3444    ->  jGetArrayLength(A, N)           % *must* be array, else undefined (crash?)
 3445    ).
 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 = []
    ).
 3467jpl_array_to_list(A, Es) :-
 3468    jpl_array_to_length(A, Len),
 3469    (   Len > 0
 3470    ->  LoBound is 0,
 3471        HiBound is Len-1,
 3472        jpl_get(A, LoBound-HiBound, Es)
 3473    ;   Es = []
 3474    ).
 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

 3489jpl_datums_to_array(Ds, A) :-
 3490    ground(Ds),
 3491    jpl_datums_to_most_specific_common_ancestor_type(Ds, T),    % T may be pseudo e.g. char_byte
 3492    jpl_type_to_preferred_concrete_type(T, Tc),    % bugfix added 16/Apr/2005
 3493    jpl_new(array(Tc), Ds, A).
 jpl_enumeration_element(+Enumeration:jref, -Element:datum)
Generates each Element from Enumeration.
 3504jpl_enumeration_element(En, E) :-
 3505    (   jpl_call(En, hasMoreElements, [], @(true))
 3506    ->  jpl_call(En, nextElement, [], Ex),
 3507        (   E = Ex
 3508        ;   jpl_enumeration_element(En, E)
 3509        )
 3510    ).
 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 = []
    ).
 3531jpl_enumeration_to_list(Enumeration, Es) :-
 3532    (   jpl_call(Enumeration, hasMoreElements, [], @(true))
 3533    ->  jpl_call(Enumeration, nextElement, [], E),
 3534        Es = [E|Es1],
 3535        jpl_enumeration_to_list(Enumeration, Es1)
 3536    ;   Es = []
 3537    ).
 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.

 3549jpl_hashtable_pair(HT, K-V) :-
 3550    jpl_call(HT, keys, [], Ek),
 3551    jpl_enumeration_to_list(Ek, Ks),
 3552    member(K, Ks),
 3553    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)
        )
    ).
 3573jpl_iterator_element(I, E) :-
 3574    (   jpl_call(I, hasNext, [], @(true))
 3575    ->  (   jpl_call(I, next, [], E)
 3576        ;   jpl_iterator_element(I, E)
 3577        )
 3578    ).
 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.

 3591jpl_list_to_array(Ds, A) :-
 3592    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.

 3602jpl_terms_to_array(Ts, A) :-
 3603    jpl_terms_to_array_1(Ts, Ts2),
 3604    jpl_new(array(class([org,jpl7],['Term'])), Ts2, A).
 3605
 3606
 3607jpl_terms_to_array_1([], []).
 3608jpl_terms_to_array_1([T|Ts], [{T}|Ts2]) :-
 3609    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.
 3618jpl_array_to_terms(JRef, Terms) :-
 3619    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).
 3648jpl_map_element(Map, K-V) :-
 3649    jpl_call(Map, entrySet, [], ES),
 3650    jpl_set_element(ES, E),
 3651    jpl_call(E, getKey, [], K),
 3652    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).
 3669jpl_set_element(S, E) :-
 3670    jpl_call(S, iterator, [], I),
 3671    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
 3683jpl_servlet_byref(Config, Request, Response) :-
 3684    jpl_call(Config, getServletContext, [], Context),
 3685    jpl_call(Response, setStatus, [200], _),
 3686    jpl_call(Response, setContentType, ['text/html'], _),
 3687    jpl_call(Response, getWriter, [], W),
 3688    jpl_call(W, println, ['<html><head></head><body><h2>jpl_servlet_byref/3 says:</h2><pre>'], _),
 3689    jpl_call(W, println, ['\nservlet context stuff:'], _),
 3690    jpl_call(Context, getInitParameterNames, [], ContextInitParameterNameEnum),
 3691    jpl_enumeration_to_list(ContextInitParameterNameEnum, ContextInitParameterNames),
 3692    length(ContextInitParameterNames, NContextInitParameterNames),
 3693    atomic_list_concat(['\tContext.InitParameters = ',NContextInitParameterNames], NContextInitParameterNamesMsg),
 3694    jpl_call(W, println, [NContextInitParameterNamesMsg], _),
 3695    (   member(ContextInitParameterName, ContextInitParameterNames),
 3696        jpl_call(Context, getInitParameter, [ContextInitParameterName], ContextInitParameter),
 3697        atomic_list_concat(['\t\tContext.InitParameter[',ContextInitParameterName,'] = ',ContextInitParameter], ContextInitParameterMsg),
 3698        jpl_call(W, println, [ContextInitParameterMsg], _),
 3699        fail
 3700    ;   true
 3701    ),
 3702    jpl_call(Context, getMajorVersion, [], MajorVersion),
 3703    atomic_list_concat(['\tContext.MajorVersion = ',MajorVersion], MajorVersionMsg),
 3704    jpl_call(W, println, [MajorVersionMsg], _),
 3705    jpl_call(Context, getMinorVersion, [], MinorVersion),
 3706    atomic_list_concat(['\tContext.MinorVersion = ',MinorVersion], MinorVersionMsg),
 3707    jpl_call(W, println, [MinorVersionMsg], _),
 3708    jpl_call(Context, getServerInfo, [], ServerInfo),
 3709    atomic_list_concat(['\tContext.ServerInfo = ',ServerInfo], ServerInfoMsg),
 3710    jpl_call(W, println, [ServerInfoMsg], _),
 3711    jpl_call(W, println, ['\nservlet config stuff:'], _),
 3712    jpl_call(Config, getServletName, [], ServletName),
 3713    (   ServletName == @(null)
 3714    ->  ServletNameAtom = null
 3715    ;   ServletNameAtom = ServletName
 3716    ),
 3717    atomic_list_concat(['\tConfig.ServletName = ',ServletNameAtom], ServletNameMsg),
 3718    jpl_call(W, println, [ServletNameMsg], _),
 3719    jpl_call(Config, getInitParameterNames, [], ConfigInitParameterNameEnum),
 3720    jpl_enumeration_to_list(ConfigInitParameterNameEnum, ConfigInitParameterNames),
 3721    length(ConfigInitParameterNames, NConfigInitParameterNames),
 3722    atomic_list_concat(['\tConfig.InitParameters = ',NConfigInitParameterNames], NConfigInitParameterNamesMsg),
 3723    jpl_call(W, println, [NConfigInitParameterNamesMsg], _),
 3724    (   member(ConfigInitParameterName, ConfigInitParameterNames),
 3725        jpl_call(Config, getInitParameter, [ConfigInitParameterName], ConfigInitParameter),
 3726        atomic_list_concat(['\t\tConfig.InitParameter[',ConfigInitParameterName,'] = ',ConfigInitParameter], ConfigInitParameterMsg),
 3727        jpl_call(W, println, [ConfigInitParameterMsg], _),
 3728        fail
 3729    ;   true
 3730    ),
 3731    jpl_call(W, println, ['\nrequest stuff:'], _),
 3732    jpl_call(Request, getAttributeNames, [], AttributeNameEnum),
 3733    jpl_enumeration_to_list(AttributeNameEnum, AttributeNames),
 3734    length(AttributeNames, NAttributeNames),
 3735    atomic_list_concat(['\tRequest.Attributes = ',NAttributeNames], NAttributeNamesMsg),
 3736    jpl_call(W, println, [NAttributeNamesMsg], _),
 3737    (   member(AttributeName, AttributeNames),
 3738        jpl_call(Request, getAttribute, [AttributeName], Attribute),
 3739        jpl_call(Attribute, toString, [], AttributeString),
 3740        atomic_list_concat(['\t\tRequest.Attribute[',AttributeName,'] = ',AttributeString], AttributeMsg),
 3741        jpl_call(W, println, [AttributeMsg], _),
 3742        fail
 3743    ;   true
 3744    ),
 3745    jpl_call(Request, getCharacterEncoding, [], CharacterEncoding),
 3746    (   CharacterEncoding == @(null)
 3747    ->  CharacterEncodingAtom = ''
 3748    ;   CharacterEncodingAtom = CharacterEncoding
 3749    ),
 3750    atomic_list_concat(['\tRequest.CharacterEncoding',' = ',CharacterEncodingAtom], CharacterEncodingMsg),
 3751    jpl_call(W, println, [CharacterEncodingMsg], _),
 3752    jpl_call(Request, getContentLength, [], ContentLength),
 3753    atomic_list_concat(['\tRequest.ContentLength',' = ',ContentLength], ContentLengthMsg),
 3754    jpl_call(W, println, [ContentLengthMsg], _),
 3755    jpl_call(Request, getContentType, [], ContentType),
 3756    (   ContentType == @(null)
 3757    ->  ContentTypeAtom = ''
 3758    ;   ContentTypeAtom = ContentType
 3759    ),
 3760    atomic_list_concat(['\tRequest.ContentType',' = ',ContentTypeAtom], ContentTypeMsg),
 3761    jpl_call(W, println, [ContentTypeMsg], _),
 3762    jpl_call(Request, getParameterNames, [], ParameterNameEnum),
 3763    jpl_enumeration_to_list(ParameterNameEnum, ParameterNames),
 3764    length(ParameterNames, NParameterNames),
 3765    atomic_list_concat(['\tRequest.Parameters = ',NParameterNames], NParameterNamesMsg),
 3766    jpl_call(W, println, [NParameterNamesMsg], _),
 3767    (   member(ParameterName, ParameterNames),
 3768        jpl_call(Request, getParameter, [ParameterName], Parameter),
 3769        atomic_list_concat(['\t\tRequest.Parameter[',ParameterName,'] = ',Parameter], ParameterMsg),
 3770        jpl_call(W, println, [ParameterMsg], _),
 3771        fail
 3772    ;   true
 3773    ),
 3774    jpl_call(Request, getProtocol, [], Protocol),
 3775    atomic_list_concat(['\tRequest.Protocol',' = ',Protocol], ProtocolMsg),
 3776    jpl_call(W, println, [ProtocolMsg], _),
 3777    jpl_call(Request, getRemoteAddr, [], RemoteAddr),
 3778    atomic_list_concat(['\tRequest.RemoteAddr',' = ',RemoteAddr], RemoteAddrMsg),
 3779    jpl_call(W, println, [RemoteAddrMsg], _),
 3780    jpl_call(Request, getRemoteHost, [], RemoteHost),
 3781    atomic_list_concat(['\tRequest.RemoteHost',' = ',RemoteHost], RemoteHostMsg),
 3782    jpl_call(W, println, [RemoteHostMsg], _),
 3783    jpl_call(Request, getScheme, [], Scheme),
 3784    atomic_list_concat(['\tRequest.Scheme',' = ',Scheme], SchemeMsg),
 3785    jpl_call(W, println, [SchemeMsg], _),
 3786    jpl_call(Request, getServerName, [], ServerName),
 3787    atomic_list_concat(['\tRequest.ServerName',' = ',ServerName], ServerNameMsg),
 3788    jpl_call(W, println, [ServerNameMsg], _),
 3789    jpl_call(Request, getServerPort, [], ServerPort),
 3790    atomic_list_concat(['\tRequest.ServerPort',' = ',ServerPort], ServerPortMsg),
 3791    jpl_call(W, println, [ServerPortMsg], _),
 3792    jpl_call(Request, isSecure, [], @(Secure)),
 3793    atomic_list_concat(['\tRequest.Secure',' = ',Secure], SecureMsg),
 3794    jpl_call(W, println, [SecureMsg], _),
 3795    jpl_call(W, println, ['\nHTTP request stuff:'], _),
 3796    jpl_call(Request, getAuthType, [], AuthType),
 3797    (   AuthType == @(null)
 3798    ->  AuthTypeAtom = ''
 3799    ;   AuthTypeAtom = AuthType
 3800    ),
 3801    atomic_list_concat(['\tRequest.AuthType',' = ',AuthTypeAtom], AuthTypeMsg),
 3802    jpl_call(W, println, [AuthTypeMsg], _),
 3803    jpl_call(Request, getContextPath, [], ContextPath),
 3804    (   ContextPath == @(null)
 3805    ->  ContextPathAtom = ''
 3806    ;   ContextPathAtom = ContextPath
 3807    ),
 3808    atomic_list_concat(['\tRequest.ContextPath',' = ',ContextPathAtom], ContextPathMsg),
 3809    jpl_call(W, println, [ContextPathMsg], _),
 3810    jpl_call(Request, getCookies, [], CookieArray),
 3811    (   CookieArray == @(null)
 3812    ->  Cookies = []
 3813    ;   jpl_array_to_list(CookieArray, Cookies)
 3814    ),
 3815    length(Cookies, NCookies),
 3816    atomic_list_concat(['\tRequest.Cookies',' = ',NCookies], NCookiesMsg),
 3817    jpl_call(W, println, [NCookiesMsg], _),
 3818    (   nth0(NCookie, Cookies, Cookie),
 3819        atomic_list_concat(['\t\tRequest.Cookie[',NCookie,']'], CookieMsg),
 3820        jpl_call(W, println, [CookieMsg], _),
 3821        jpl_call(Cookie, getName, [], CookieName),
 3822        atomic_list_concat(['\t\t\tRequest.Cookie.Name = ',CookieName], CookieNameMsg),
 3823        jpl_call(W, println, [CookieNameMsg], _),
 3824        jpl_call(Cookie, getValue, [], CookieValue),
 3825        atomic_list_concat(['\t\t\tRequest.Cookie.Value = ',CookieValue], CookieValueMsg),
 3826        jpl_call(W, println, [CookieValueMsg], _),
 3827        jpl_call(Cookie, getPath, [], CookiePath),
 3828        (   CookiePath == @(null)
 3829        ->  CookiePathAtom = ''
 3830        ;   CookiePathAtom = CookiePath
 3831        ),
 3832        atomic_list_concat(['\t\t\tRequest.Cookie.Path = ',CookiePathAtom], CookiePathMsg),
 3833        jpl_call(W, println, [CookiePathMsg], _),
 3834        jpl_call(Cookie, getComment, [], CookieComment),
 3835        (   CookieComment == @(null)
 3836        ->  CookieCommentAtom = ''
 3837        ;   CookieCommentAtom = CookieComment
 3838        ),
 3839        atomic_list_concat(['\t\t\tRequest.Cookie.Comment = ',CookieCommentAtom], CookieCommentMsg),
 3840        jpl_call(W, println, [CookieCommentMsg], _),
 3841        jpl_call(Cookie, getDomain, [], CookieDomain),
 3842        (   CookieDomain == @(null)
 3843        ->  CookieDomainAtom = ''
 3844        ;   CookieDomainAtom = CookieDomain
 3845        ),
 3846        atomic_list_concat(['\t\t\tRequest.Cookie.Domain = ',CookieDomainAtom], CookieDomainMsg),
 3847        jpl_call(W, println, [CookieDomainMsg], _),
 3848        jpl_call(Cookie, getMaxAge, [], CookieMaxAge),
 3849        atomic_list_concat(['\t\t\tRequest.Cookie.MaxAge = ',CookieMaxAge], CookieMaxAgeMsg),
 3850        jpl_call(W, println, [CookieMaxAgeMsg], _),
 3851        jpl_call(Cookie, getVersion, [], CookieVersion),
 3852        atomic_list_concat(['\t\t\tRequest.Cookie.Version = ',CookieVersion], CookieVersionMsg),
 3853        jpl_call(W, println, [CookieVersionMsg], _),
 3854        jpl_call(Cookie, getSecure, [], @(CookieSecure)),
 3855        atomic_list_concat(['\t\t\tRequest.Cookie.Secure',' = ',CookieSecure], CookieSecureMsg),
 3856        jpl_call(W, println, [CookieSecureMsg], _),
 3857        fail
 3858    ;   true
 3859    ),
 3860    jpl_call(W, println, ['</pre></body></html>'], _),
 3861    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).
 3871jpl_servlet_byval(MM, CT, Ba) :-
 3872    CT = 'text/html',
 3873    multimap_to_atom(MM, MMa),
 3874    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).
 3881is_pair(Key-_Val) :-
 3882    ground(Key).
 3883
 3884
 3885is_pairs(List) :-
 3886    is_list(List),
 3887    maplist(is_pair, List).
 3888
 3889
 3890multimap_to_atom(KVs, A) :-
 3891    multimap_to_atom_1(KVs, '', Cz, []),
 3892    flatten(Cz, Cs),
 3893    atomic_list_concat(Cs, A).
 3894
 3895
 3896multimap_to_atom_1([], _, Cs, Cs).
 3897multimap_to_atom_1([K-V|KVs], T, Cs1, Cs0) :-
 3898    Cs1 = [T,K,' = '|Cs2],
 3899    (   is_list(V)
 3900    ->  (   is_pairs(V)
 3901        ->  V = V2
 3902        ;   findall(N-Ve, nth1(N, V, Ve), V2)
 3903        ),
 3904        T2 = ['    ',T],
 3905        Cs2 = ['\n'|Cs2a],
 3906        multimap_to_atom_1(V2, T2, Cs2a, Cs3)
 3907    ;   to_atom(V, AV),
 3908        Cs2 = [AV,'\n'|Cs3]
 3909    ),
 3910    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),...)
 3919to_atom(Term, Atom) :-
 3920    (   atom(Term)
 3921    ->  Atom = Term                % avoid superfluous quotes
 3922    ;   term_to_atom(Term, Atom)
 3923    ).
 jpl_pl_syntax(-Syntax:atom)
Unifies Syntax with 'traditional' or 'modern' according to the mode in which SWI Prolog 7.x was started
 3930jpl_pl_syntax(Syntax) :-
 3931	(	[] == '[]'
 3932	->	Syntax = traditional
 3933	;	Syntax = modern
 3934	).
 3935
 3936         /*******************************
 3937         *            MESSAGES          *
 3938         *******************************/
 3939
 3940:- multifile
 3941    prolog:error_message/3. 3942
 3943prolog:error_message(java_exception(Ex)) -->
 3944    (   { jpl_call(Ex, toString, [], Msg)
 3945        }
 3946    ->  [ 'Java exception: ~w'-[Msg] ]
 3947    ;   [ 'Java exception: ~w'-[Ex] ]
 3948    ).
 3949
 3950
 3951         /*******************************
 3952         *             PATHS            *
 3953         *******************************/
 3954
 3955:- multifile user:file_search_path/2. 3956:- dynamic   user:file_search_path/2. 3957
 3958user:file_search_path(jar, swi(lib)).
 3959
 3960classpath(DirOrJar) :-
 3961    getenv('CLASSPATH', ClassPath),
 3962    (   current_prolog_flag(windows, true)
 3963    ->  atomic_list_concat(Elems, (;), ClassPath)
 3964    ;   atomic_list_concat(Elems, :, ClassPath)
 3965    ),
 3966    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.
 3975add_search_path(Path, Dir) :-
 3976    (   getenv(Path, Old)
 3977    ->  search_path_separator(Sep),
 3978        (   atomic_list_concat(Current, Sep, Old),
 3979            memberchk(Dir, Current)
 3980        ->  true            % already present
 3981        ;   atomic_list_concat([Old, Sep, Dir], New),
 3982            (   debugging(jpl(path))
 3983            ->  env_var_separators(A,Z),
 3984                debug(jpl(path), 'Set ~w~w~w to ~p', [A,Path,Z,New])
 3985            ;   true
 3986            ),
 3987            setenv(Path, New)
 3988        )
 3989    ;   setenv(Path, Dir)
 3990    ).
 search_path_separator(-Sep:atom)
Separator used the the OS in PATH, LD_LIBRARY_PATH, CLASSPATH, etc.
 3997search_path_separator((;)) :-
 3998    current_prolog_flag(windows, true),
 3999    !.
 4000search_path_separator(:).
 4001
 4002env_var_separators('%','%') :-
 4003    current_prolog_flag(windows, true),
 4004    !.
 4005env_var_separators($,'').
 4006
 4007
 4008         /*******************************
 4009         *         LOAD THE JVM         *
 4010         *******************************/
 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.

 4028check_java_environment :-
 4029    current_prolog_flag(apple, true),
 4030    !,
 4031    print_message(error, jpl(run(jpl_config_dylib))).
 4032check_java_environment :-
 4033    check_lib(jvm).
 4034
 4035check_lib(Name) :-
 4036    check_shared_object(Name, File, EnvVar, Absolute),
 4037    (   Absolute == (-)
 4038    ->  env_var_separators(A, Z),
 4039        format(string(Msg), 'Please add directory holding ~w to ~w~w~w',
 4040               [ File, A, EnvVar, Z ]),
 4041        throw(error(existence_error(library, Name),
 4042                    context(_, Msg)))
 4043    ;   true
 4044    ).
 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.
 4053check_shared_object(Name, File, EnvVar, Absolute) :-
 4054    libfile(Name, File),
 4055    library_search_path(Path, EnvVar),
 4056    (   member(Dir, Path),
 4057        atomic_list_concat([Dir, File], /, Absolute),
 4058        exists_file(Absolute)
 4059    ->  true
 4060    ;   Absolute = (-)
 4061    ).
 4062
 4063libfile(Base, File) :-
 4064    current_prolog_flag(unix, true),
 4065    !,
 4066    atom_concat(lib, Base, F0),
 4067    current_prolog_flag(shared_object_extension, Ext),
 4068    file_name_extension(F0, Ext, File).
 4069libfile(Base, File) :-
 4070    current_prolog_flag(windows, true),
 4071    !,
 4072    current_prolog_flag(shared_object_extension, Ext),
 4073    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.
 4081library_search_path(Path, EnvVar) :-
 4082    current_prolog_flag(shared_object_search_path, EnvVar),
 4083    search_path_separator(Sep),
 4084    (   getenv(EnvVar, Env),
 4085        atomic_list_concat(Path, Sep, Env)
 4086    ->  true
 4087    ;   Path = []
 4088    ).
 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?
 4102add_jpl_to_classpath :-
 4103    classpath(Jar),
 4104    file_base_name(Jar, 'jpl.jar'),
 4105    !.
 4106add_jpl_to_classpath :-
 4107    classpath(Dir),
 4108    directory_file_path(Dir, 'jpl.jar', File),
 4109    access_file(File, read),
 4110    !.
 4111add_jpl_to_classpath :-
 4112    absolute_file_name(jar('jpl.jar'), JplJAR,
 4113                       [ access(read)
 4114                       ]),
 4115    !,
 4116    (   getenv('CLASSPATH', Old)
 4117    ->  search_path_separator(Separator),
 4118        atomic_list_concat([JplJAR, Old], Separator, New)
 4119    ;   New = JplJAR
 4120    ),
 4121    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.
 4130libjpl(File) :-
 4131    (   current_prolog_flag(unix, true)
 4132    ->  File = foreign(libjpl)
 4133    ;   File = foreign(jpl)
 4134    ).
 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.
 4143add_jpl_to_ldpath(JPL) :-
 4144    absolute_file_name(JPL, File,
 4145               [ file_type(executable),
 4146                 access(read),
 4147                 file_errors(fail)
 4148               ]),
 4149    !,
 4150    file_directory_name(File, Dir),
 4151    prolog_to_os_filename(Dir, OsDir),
 4152    extend_java_library_path(OsDir),
 4153    current_prolog_flag(shared_object_search_path, PathVar),
 4154    add_search_path(PathVar, OsDir).
 4155add_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.
 4164:- if(current_prolog_flag(windows,true)). 4165add_java_to_ldpath :-
 4166    current_prolog_flag(windows, true),
 4167    !,
 4168    phrase(java_dirs, Extra),
 4169    (   Extra \== []
 4170    ->  print_message(informational, extend_ld_path(Extra)),
 4171        maplist(extend_dll_search_path, Extra)
 4172    ;   true
 4173    ).
 4174:- endif. 4175add_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.
 4184:- if(current_prolog_flag(windows,true)). 4185extend_dll_search_path(Dir) :-
 4186    win_add_dll_directory(Dir),
 4187    (   current_prolog_flag(wine_version, _)
 4188    ->  getenv('PATH', Path0),
 4189        prolog_to_os_filename(Dir, OSDir),
 4190        atomic_list_concat([Path0, OSDir], ';', Path),
 4191        setenv('PATH', Path)
 4192    ;   true
 4193    ).
 4194:- endif.
 extend_java_library_path(+OsDir)
Add Dir (in OS notation) to the Java -Djava.library.path init options.
 4201extend_java_library_path(OsDir) :-
 4202    jpl_get_default_jvm_opts(Opts0),
 4203    (   select(PathOpt0, Opts0, Rest),
 4204        sub_atom(PathOpt0, 0, _, _, '-Djava.library.path=')
 4205    ->  search_path_separator(Separator),
 4206        atomic_list_concat([PathOpt0, Separator, OsDir], PathOpt),
 4207        NewOpts = [PathOpt|Rest]
 4208    ;   atom_concat('-Djava.library.path=', OsDir, PathOpt),
 4209        NewOpts = [PathOpt|Opts0]
 4210    ),
 4211    debug(jpl(path), 'Setting Java options to ~p', [NewOpts]),
 4212    jpl_set_default_jvm_opts(NewOpts).
 java_dirs// is det
DCG that produces existing candidate directories holding Java related DLLs
 4219java_dirs -->
 4220    % JDK directories
 4221    java_dir(jvm, '/jre/bin/client'),
 4222    java_dir(jvm, '/jre/bin/server'),
 4223    java_dir(java, '/jre/bin'),
 4224    % JRE directories
 4225    java_dir(jvm, '/bin/client'),
 4226    java_dir(jvm, '/bin/server'),
 4227    java_dir(java, '/bin').
 4228
 4229java_dir(DLL, _SubPath) -->
 4230    { check_shared_object(DLL, _, _Var, Abs),
 4231      Abs \== (-)
 4232    },
 4233    !.
 4234java_dir(_DLL, SubPath) -->
 4235    { java_home(JavaHome),
 4236      atom_concat(JavaHome, SubPath, SubDir),
 4237      exists_directory(SubDir)
 4238    },
 4239    !,
 4240    [SubDir].
 4241java_dir(_, _) --> [].
 java_home(-Home) is semidet
Find the home location of Java.
Arguments:
Home- JAVA home in OS notation
 4250java_home_win_key(
 4251    jre,
 4252    'HKEY_LOCAL_MACHINE/Software/JavaSoft/Java Runtime Environment').
 4253java_home_win_key(
 4254    jdk,
 4255    'HKEY_LOCAL_MACHINE/Software/JavaSoft/Java Development Kit').
 4256
 4257java_home(Home) :-
 4258    getenv('JAVA_HOME', Home),
 4259    exists_directory(Home),
 4260    !.
 4261:- if(current_prolog_flag(windows, true)). 4262java_home(Home) :-
 4263    java_home_win_key(_, Key0),    % TBD: user can't choose jre or jdk
 4264    catch(win_registry_get_value(Key0, 'CurrentVersion', Version), _, fail),
 4265    atomic_list_concat([Key0, Version], /, Key),
 4266    win_registry_get_value(Key, 'JavaHome', WinHome),
 4267    prolog_to_os_filename(Home, WinHome),
 4268    exists_directory(Home),
 4269    !.
 4270:- else. 4271java_home(Home) :-
 4272    member(Home, [ '/usr/lib/java',
 4273                   '/usr/local/lib/java'
 4274                 ]),
 4275    exists_directory(Home),
 4276    !.
 4277:- endif. 4278
 4279:- dynamic
 4280    jvm_ready/0. 4281:- volatile
 4282    jvm_ready/0. 4283
 4284setup_jvm :-
 4285    jvm_ready,
 4286    !.
 4287setup_jvm :-
 4288    add_jpl_to_classpath,
 4289    add_java_to_ldpath,
 4290    libjpl(JPL),
 4291    catch(load_foreign_library(JPL), E, report_java_setup_problem(E)),
 4292    add_jpl_to_ldpath(JPL),
 4293    assert(jvm_ready).
 4294
 4295report_java_setup_problem(E) :-
 4296    print_message(error, E),
 4297    check_java_environment.
 4298
 4299         /*******************************
 4300         *          MESSAGES        *
 4301         *******************************/
 4302
 4303:- multifile
 4304    prolog:message//1. 4305
 4306prolog:message(extend_ld_path(Dirs)) -->
 4307    [ 'Extended DLL search path with'-[] ],
 4308    dir_per_line(Dirs).
 4309prolog:message(jpl(run(Command))) -->
 4310    [ 'Could not find libjpl.dylib dependencies.'-[],
 4311      'Please run `?- ~p.` to correct this'-[Command]
 4312    ].
 4313
 4314dir_per_line([]) --> [].
 4315dir_per_line([H|T]) -->
 4316    [ nl, '  ~q'-[H] ],
 4317    dir_per_line(T).
 4318
 4319% Initialize JVM
 4320
 4321:- initialization(setup_jvm, now).        % must be ready before export