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-2020, 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(lists),
   88	    [member/2,nth0/3,nth1/3,append/3,flatten/2,select/3]).   89:- 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/ */
   98% suppress debugging this library
   99:- 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.

  129jpl_new(X, Params, V) :-
  130    Pred=jpl_new/3,
  131    (   var(X)
  132    ->  throw_instantiation_error(Pred,ea01)
  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_domain_error(Pred,classname,X,ea02)
  139        )
  140    ;   throw_type_error(Pred,instantiable,X,ea03)
  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 Vx is not a JRef to a org.jpl7.Term
  146        ->  Term = TermX
  147        ;   throw_type_error(Pred,term,Vx,ea04)
  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    Pred=jpl_new/3,
  165    !,                                      % green (see below)
  166    Tx = class(Ps,Cs),
  167    (   var(Params)
  168    ->  throw_instantiation_error(Pred,eb01)
  169    ;   \+ is_list(Params)
  170    ->  throw_type_error(Pred,list,Params,eb01)
  171    ;   true
  172    ),
  173    length(Params, A),          % the "arity" of the required constructor
  174    jpl_type_to_class(Tx, Cx),  % throws Java exception if class is not found
  175    N = '<init>',               % JNI's constructor naming convention for GetMethodID()
  176    Tr = void,                  % all constructors have this return "type"
  177    findall(
  178        z3(I,MID,Tfps),
  179        jpl_method_spec(Tx, I, N, A, _Mods, MID, Tr, Tfps), % cached
  180        Z3s
  181    ),
  182    (   Z3s == []               % no constructors which require the given qty of parameters?
  183    ->  jpl_type_to_classname(Tx, Cn),
  184        (   jpl_call(Cx, isInterface, [], @(true))
  185        ->  throw_type_error(Pred,concrete_class,Cn,eb03)
  186        ;   throw_existence_error(Pred,constructor,Cn/A,eb04)
  187        )
  188    ;   (   catch(
  189                jpl_datums_to_types(Params, Taps),  % infer actual parameter types
  190                error(type_error(acyclic,Te),context(jpl_datum_to_type/2,Msg)),
  191                throw_type_error(Pred,acyclic,Te,Msg) % rethrow
  192            )
  193        ->  true
  194        ;   throw_domain_error(Pred,list(jpl_datum),Params,eb05)
  195        ),
  196        findall(
  197            z3(I,MID,Tfps),                 % select constructors to which actual parameters are assignable
  198            (   member(z3(I,MID,Tfps), Z3s),
  199                jpl_types_fit_types(Taps, Tfps) % assignability test: actual parameter types "fit" formal parameter types?
  200            ),
  201            Z3sA
  202        ),
  203        (   Z3sA == []                      % no type-assignable constructors?
  204        ->  (   Z3s = [_]
  205            ->  throw_existence_error(Pred,constructor,Tx/A,eb06)
  206            ;   throw_type_error(Pred,constructor_args,Params,eb07)
  207            )
  208        ;   Z3sA = [z3(I,MID,Tfps)]
  209        ->  true
  210        ;   jpl_z3s_to_most_specific_z3(Z3sA, z3(I,MID,Tfps))
  211        ->  true
  212        ;   throw_type_error(Pred,constructor_params,Params,eb08)
  213        )
  214    ),
  215    catch(
  216        jNewObject(Cx, MID, Tfps, Params, Vx),
  217        error(java_exception(_), 'java.lang.InstantiationException'),
  218        (   jpl_type_to_classname(Tx, Cn),
  219            throw_type_error(Pred,concrete_class,Cn,eb09) % Rethrow
  220        )
  221    ),
  222    jpl_cache_type_of_ref(Tx, Vx).          % since we know it
  223
  224jpl_new_1(array(T), Params, Vx) :-
  225    Pred=jpl_new/3,
  226    !,
  227    (   var(Params)
  228    ->  throw_instantiation_error(Pred,ec01)
  229    ;   integer(Params)         % integer I -> array[0..I-1] of default values
  230    ->  (   Params >= 0
  231        ->  Len is Params
  232        ;   throw_domain_error(Pred,array_length,Params,ec02)
  233        )
  234    ;   is_list(Params)     % [V1,..VN] -> array[0..N-1] of respective values
  235    ->  length(Params, Len)
  236    ),
  237    jpl_new_array(T, Len, Vx), % NB may throw out-of-memory exception
  238    (   nth0(I, Params, Param),     % nmember fails silently when Params is integer
  239        jpl_set(Vx, I, Param),
  240        fail
  241    ;   true
  242    ),
  243    jpl_cache_type_of_ref(array(T), Vx).   % since we know it
  244
  245jpl_new_1(T, _Params, _Vx) :-       % doomed attempt to create new primitive type instance (formerly a dubious completist feature :-)
  246    Pred=jpl_new/3,
  247    jpl_primitive_type(T),
  248    !,
  249    throw_domain_error(Pred,object_type,T,ed01).
  250  % (   var(Params)
  251  % ->  throw_instantiation_error(Pred,ed02)
  252  % ;   Params == []
  253  % ->  jpl_primitive_type_default_value(T, Vx)
  254  % ;   Params = [Param]
  255  % ->  jpl_primitive_type_term_to_value(T, Param, Vx)
  256  % ;   throw_domain_error(Pred,constructor_args,Params,ed03)
  257  % ).
  258
  259jpl_new_1(T, _, _) :-
  260    Pred=jpl_new/3,
  261    throw_domain_error(Pred,jpl_type,T,ee01).
 jpl_new_array(+ElementType, +Length, -NewArray) is det
binds NewArray to a jref to a newly created Java array of ElementType and Length
  268jpl_new_array(boolean, Len, A) :-
  269    jNewBooleanArray(Len, A).
  270jpl_new_array(byte, Len, A) :-
  271    jNewByteArray(Len, A).
  272jpl_new_array(char, Len, A) :-
  273    jNewCharArray(Len, A).
  274jpl_new_array(short, Len, A) :-
  275    jNewShortArray(Len, A).
  276jpl_new_array(int, Len, A) :-
  277    jNewIntArray(Len, A).
  278jpl_new_array(long, Len, A) :-
  279    jNewLongArray(Len, A).
  280jpl_new_array(float, Len, A) :-
  281    jNewFloatArray(Len, A).
  282jpl_new_array(double, Len, A) :-
  283    jNewDoubleArray(Len, A).
  284jpl_new_array(array(T), Len, A) :-
  285    jpl_type_to_class(array(T), C),
  286    jNewObjectArray(Len, C, @(null), A).        % initialise each element to null
  287jpl_new_array(class(Ps,Cs), Len, A) :-
  288    jpl_type_to_class(class(Ps,Cs), C),
  289    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.

  311jpl_call(X, Mspec, Params, R) :-
  312    Pred=jpl_call/4,
  313    (   jpl_object_to_type(X, Type)         % the usual case (goal fails safely if X is var or rubbish)
  314    ->  Obj = X,
  315        Kind = instance
  316    ;   var(X)
  317    ->  throw_instantiation_error(Pred,ef01)
  318    ;   atom(X)
  319    ->  (   jpl_classname_to_type(X, Type)     % does this attempt to load the class?
  320        ->  (   jpl_type_to_class(Type, ClassObj)
  321            ->  Kind = static
  322            ;   throw_existence_error(Pred,class,X,ef02)
  323            )
  324        ;   throw_type_error(Pred,class_name_or_descriptor,X,ef03)
  325        )
  326    ;   X = class(_,_)
  327    ->  Type = X,
  328        jpl_type_to_class(Type, ClassObj),
  329        Kind = static
  330    ;   X = array(_)
  331    ->  throw_type_error(Pred,object_or_class,X,ef04)
  332    ;   throw_domain_error(Pred,object_or_class,X,ef03)
  333    ),
  334    (   atom(Mspec)                 % the usual case, i.e. a method name
  335    ->  true
  336    ;   var(Mspec)
  337    ->  throw_instantiation_error(Pred,ef05)
  338    ;   throw_type_error(Pred,method_name,Mspec,ef05)
  339    ),
  340    (   is_list(Params)
  341    ->  (   catch(
  342                jpl_datums_to_types(Params, Taps),
  343                error(type_error(acyclic,Te),context(jpl_datum_to_type/2,Msg)),
  344                throw_type_error(Pred,acyclic,Te,Msg) % Rethrow
  345            )
  346        ->  true
  347        ;   throw_type_error(Pred,method_params,Params,ef06)
  348        ),
  349        length(Params, A)
  350    ;   var(Params)
  351    ->  throw_instantiation_error(Pred,ef07)
  352    ;   throw_type_error(Pred,method_params,Params,ef07)
  353    ),
  354    (   Kind == instance
  355    ->  jpl_call_instance(Type, Obj, Mspec, Params, Taps, A, Rx)
  356    ;   jpl_call_static(Type, ClassObj, Mspec, Params, Taps, A, Rx)
  357    ),
  358    (   nonvar(R),
  359        R = {Term}  % yucky way of requesting Term->term conversion
  360    ->  (   jni_jref_to_term(Rx, TermX)    % fails if Rx isn't a JRef to a org.jpl7.Term
  361        ->  Term = TermX
  362        ;   throw_type_error(Pred,jni_jref,Rx,ef08)
  363        )
  364    ;   R = Rx
  365    ).
 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.
  375jpl_call_instance(Type, Obj, Mname, Params, Taps, A, Rx) :-
  376    Pred=jpl_call/4,
  377    findall(                    % get remaining details of all accessible methods of Obj's class (as denoted by Type)
  378        z5(I,Mods,MID,Tr,Tfps),
  379        jpl_method_spec(Type, I, Mname, A, Mods, MID, Tr, Tfps),
  380        Z5s
  381    ),
  382    (   Z5s = []
  383    ->  throw_existence_error(Pred,method,Mname/A,eg01)
  384    ;   findall(
  385            z5(I,Mods,MID,Tr,Tfps),             % those to which Params is assignable
  386            (   member(z5(I,Mods,MID,Tr,Tfps), Z5s),
  387                jpl_types_fit_types(Taps, Tfps) % assignability test: actual param types "fit" formal param types
  388            ),
  389            Z5sA                                % Params-assignable methods
  390        ),
  391        (   Z5sA == []
  392        ->  throw_type_error(Pred,method_params,Params,eg02)
  393        ;   Z5sA = [z5(I,Mods,MID,Tr,Tfps)]
  394        ->  true                                % exactly one applicable method
  395        ;   jpl_z5s_to_most_specific_z5(Z5sA, z5(I,Mods,MID,Tr,Tfps))
  396        ->  true                                % exactly one most-specific applicable method
  397        ;   throw_existence_error(Pred,most_specific_method,Mname/Params,eg03)
  398        )
  399    ),
  400    (   member(static, Mods)                                        % if the chosen method is static
  401    ->  jpl_object_to_class(Obj, ClassObj),                         % get a java.lang.Class instance which personifies Obj's class
  402        jpl_call_static_method(Tr, ClassObj, MID, Tfps, Params, Rx) % call static method w.r.t. associated Class object
  403    ;   jpl_call_instance_method(Tr, Obj, MID, Tfps, Params, Rx)    % else call (non-static) method w.r.t. object itself
  404    ).
 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.
  415jpl_call_static(Type, ClassObj, Mname, Params, Taps, A, Rx) :-
  416    Pred=jpl_call/4,
  417    findall(                    % get all accessible static methods of the class denoted by Type and ClassObj
  418        z5(I,Mods,MID,Tr,Tfps),
  419        (   jpl_method_spec(Type, I, Mname, A, Mods, MID, Tr, Tfps),
  420            member(static, Mods)
  421        ),
  422        Z5s
  423    ),
  424    (   Z5s = []
  425    ->  throw_existence_error(Pred,method,Mname/A,eh01)
  426    ;   findall(
  427            z5(I,Mods,MID,Tr,Tfps),
  428            (   member(z5(I,Mods,MID,Tr,Tfps), Z5s),
  429                jpl_types_fit_types(Taps, Tfps) % assignability test: actual param types "fit" formal param types
  430            ),
  431            Z5sA                                % Params-assignable methods
  432        ),
  433        (   Z5sA == []
  434        ->  throw_type_error(Pred,method_params,Params,eh02)
  435        ;   Z5sA = [z5(I,Mods,MID,Tr,Tfps)]
  436        ->  true                % exactly one applicable method
  437        ;   jpl_z5s_to_most_specific_z5(Z5sA, z5(I,Mods,MID,Tr,Tfps))
  438        ->  true                % exactly one most-specific applicable method
  439        ;   throw_existence_error(Pred,most_specific_method,Mname/Params,eh03)
  440        )
  441    ),
  442    jpl_call_static_method(Tr, ClassObj, MID, Tfps, Params, Rx).
 jpl_call_instance_method(+Type, +ClassObject, +MethodID, +FormalParamTypes, +Params, -Result)
  447jpl_call_instance_method(void, Class, MID, Tfps, Ps, R) :-
  448    jCallVoidMethod(Class, MID, Tfps, Ps),
  449    jpl_void(R).
  450jpl_call_instance_method(boolean, Class, MID, Tfps, Ps, R) :-
  451    jCallBooleanMethod(Class, MID, Tfps, Ps, R).
  452jpl_call_instance_method(byte, Class, MID, Tfps, Ps, R) :-
  453    jCallByteMethod(Class, MID, Tfps, Ps, R).
  454jpl_call_instance_method(char, Class, MID, Tfps, Ps, R) :-
  455    jCallCharMethod(Class, MID, Tfps, Ps, R).
  456jpl_call_instance_method(short, Class, MID, Tfps, Ps, R) :-
  457    jCallShortMethod(Class, MID, Tfps, Ps, R).
  458jpl_call_instance_method(int, Class, MID, Tfps, Ps, R) :-
  459    jCallIntMethod(Class, MID, Tfps, Ps, R).
  460jpl_call_instance_method(long, Class, MID, Tfps, Ps, R) :-
  461    jCallLongMethod(Class, MID, Tfps, Ps, R).
  462jpl_call_instance_method(float, Class, MID, Tfps, Ps, R) :-
  463    jCallFloatMethod(Class, MID, Tfps, Ps, R).
  464jpl_call_instance_method(double, Class, MID, Tfps, Ps, R) :-
  465    jCallDoubleMethod(Class, MID, Tfps, Ps, R).
  466jpl_call_instance_method(array(_), Class, MID, Tfps, Ps, R) :-
  467    jCallObjectMethod(Class, MID, Tfps, Ps, R).
  468jpl_call_instance_method(class(_,_), Class, MID, Tfps, Ps, R) :-
  469    jCallObjectMethod(Class, MID, Tfps, Ps, R).
 jpl_call_static_method(+Type, +ClassObject, +MethodID, +FormalParamTypes, +Params, -Result)
  474jpl_call_static_method(void, Class, MID, Tfps, Ps, R) :-
  475    jCallStaticVoidMethod(Class, MID, Tfps, Ps),
  476    jpl_void(R).
  477jpl_call_static_method(boolean, Class, MID, Tfps, Ps, R) :-
  478    jCallStaticBooleanMethod(Class, MID, Tfps, Ps, R).
  479jpl_call_static_method(byte, Class, MID, Tfps, Ps, R) :-
  480    jCallStaticByteMethod(Class, MID, Tfps, Ps, R).
  481jpl_call_static_method(char, Class, MID, Tfps, Ps, R) :-
  482    jCallStaticCharMethod(Class, MID, Tfps, Ps, R).
  483jpl_call_static_method(short, Class, MID, Tfps, Ps, R) :-
  484    jCallStaticShortMethod(Class, MID, Tfps, Ps, R).
  485jpl_call_static_method(int, Class, MID, Tfps, Ps, R) :-
  486    jCallStaticIntMethod(Class, MID, Tfps, Ps, R).
  487jpl_call_static_method(long, Class, MID, Tfps, Ps, R) :-
  488    jCallStaticLongMethod(Class, MID, Tfps, Ps, R).
  489jpl_call_static_method(float, Class, MID, Tfps, Ps, R) :-
  490    jCallStaticFloatMethod(Class, MID, Tfps, Ps, R).
  491jpl_call_static_method(double, Class, MID, Tfps, Ps, R) :-
  492    jCallStaticDoubleMethod(Class, MID, Tfps, Ps, R).
  493jpl_call_static_method(array(_), Class, MID, Tfps, Ps, R) :-
  494    jCallStaticObjectMethod(Class, MID, Tfps, Ps, R).
  495jpl_call_static_method(class(_,_), Class, MID, Tfps, Ps, R) :-
  496    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].
  528jpl_get(X, Fspec, V) :-
  529    Pred=jpl_get/3,
  530    (   jpl_object_to_type(X, Type)
  531    ->  Obj = X,
  532        jpl_get_instance(Type, Type, Obj, Fspec, Vx)   % pass Type twice for FAI
  533    ;   var(X)
  534    ->  throw_instantiation_error(Pred,ei01)
  535    ;   jpl_is_type(X)          % e.g. class([java,lang],['String']), array(int)
  536    ->  Type = X,
  537        (   jpl_type_to_class(Type, ClassObj)
  538        ->  jpl_get_static(Type, ClassObj, Fspec, Vx)
  539        ;   jpl_type_to_classname(Type, Classname),
  540            throw_existence_error(Pred,class,Classname,ei02)
  541        )
  542    ;   atom(X)
  543    ->  (   jpl_classname_to_type(X, Type)     % does this attempt to load the class?
  544        ->  (   jpl_type_to_class(Type, ClassObj)
  545            ->  jpl_get_static(Type, ClassObj, Fspec, Vx)
  546            ;   throw_existence_error(Pred,class,X,ei02)
  547            )
  548        ;   throw_type_error(Pred,class_name_or_descriptor,X,ei03)
  549        )
  550    ;   throw_domain_error(Pred,object_or_class,X,ei03)
  551    ),
  552    (   nonvar(V),
  553        V = {Term}  % yucky way of requesting Term->term conversion
  554    ->  (   jni_jref_to_term(Vx, TermX)    % fails if Rx is not a JRef to a org.jpl7.Term
  555        ->  Term = TermX
  556        ;   throw_type_error(Pred,jni_jref,Vx,ei04)
  557        )
  558    ;   V = Vx
  559    ).
 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
  569jpl_get_static(Type, ClassObj, Fname, Vx) :-
  570    Pred=jpl_get/3,
  571    (   atom(Fname)             % assume it's a field name
  572    ->  true
  573    ;   var(Fname)
  574    ->  throw_instantiation_error(Pred,ej01)
  575    ;   throw_type_error(Pred,field_name,Fname,ej02)
  576    ),
  577  % get static fields of the denoted class
  578    findall(
  579        z4(I,Mods,FID,Tf),
  580        (   jpl_field_spec(Type, I, Fname, Mods, FID, Tf),
  581            member(static, Mods)
  582        ),
  583        Z4s
  584    ),
  585    (   Z4s = []
  586    ->  throw_existence_error(Pred,field,Fname,ej03)
  587    ;   Z4s = [z4(I,_Mods,FID,Tf)]
  588    ->  jpl_get_static_field(Tf, ClassObj, FID, Vx)
  589    ;   throw_existence_error(Pred,unique_field,Fname,ej04)
  590    ).
 jpl_get_instance(+Type, +Type, +Object, +FieldSpecifier, -Value) is det
  595jpl_get_instance(class(_,_), Type, Obj, Fname, Vx) :-
  596    Pred=jpl_get/3,
  597    (   atom(Fname)                 % the usual case
  598    ->  true
  599    ;   var(Fname)
  600    ->  throw_instantiation_error(Pred,ek01)
  601    ;   throw_type_error(Pred,field_name,Fname,ek02)
  602    ),
  603    findall(
  604        z4(I,Mods,FID,Tf),
  605        jpl_field_spec(Type, I, Fname, Mods, FID, Tf),
  606        Z4s
  607    ),
  608    (   Z4s = []
  609    ->  throw_existence_error(Pred,field,Fname,ek03)
  610    ;   Z4s = [z4(I,Mods,FID,Tf)]
  611    ->  (   member(static, Mods)
  612        ->  jpl_object_to_class(Obj, ClassObj),
  613            jpl_get_static_field(Tf, ClassObj, FID, Vx)
  614        ;   jpl_get_instance_field(Tf, Obj, FID, Vx)
  615        )
  616    ;   throw_existence_error(Pred,unique_field,Fname,ek04)
  617    ).
  618
  619jpl_get_instance(array(ElementType), _, Array, Fspec, Vx) :-
  620    Pred=jpl_get/3,
  621    (   var(Fspec)
  622    ->  throw_instantiation_error(Pred,el01)
  623    ;   integer(Fspec)
  624    ->  (   Fspec < 0       % lo bound check
  625        ->  throw_domain_error(Pred,array_index,Fspec,el02)
  626        ;   jGetArrayLength(Array, Len),
  627            Fspec >= Len    % hi bound check
  628        ->  throw_domain_error(Pred,array_index,Fspec,el03)
  629        ;   jpl_get_array_element(ElementType, Array, Fspec, Vx)
  630        )
  631    ;   Fspec = N-M     % NB should we support e.g. 3-2 -> [] ?
  632    ->  (   integer(N),
  633            integer(M)
  634        ->  (   N >= 0,
  635                M >= N
  636            ->  jGetArrayLength(Array, Len),
  637                (   N >= Len
  638                ->  throw_domain_error(Pred,array_index_range,N-M,el04)
  639                ;   M >= Len
  640                ->  throw_domain_error(Pred,array_index_range,N-M,el05)
  641                ;   jpl_get_array_elements(ElementType, Array, N, M, Vx)
  642                )
  643            ;   throw_domain_error(Pred,array_index_range,N-M,el06)
  644            )
  645        ;   throw_type_error(Pred,array_index_range,N-M,el06)
  646        )
  647    ;   atom(Fspec)
  648    ->  (   Fspec == length             % special-case for this solitary array "method"
  649        ->  jGetArrayLength(Array, Vx)
  650        ;   throw_domain_error(Pred,array_field_name,Fspec,el07)
  651        )
  652    ;   throw_type_error(Pred,array_lookup_spec,Fspec,el08)
  653    ).
 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
  665jpl_get_array_element(Type, Array, Index, Vc) :-
  666    (   (   Type = class(_,_)
  667        ;   Type = array(_)
  668        )
  669    ->  jGetObjectArrayElement(Array, Index, Vr)
  670    ;   jpl_primitive_type(Type)
  671    ->  jni_type_to_xput_code(Type, Xc),
  672        jni_alloc_buffer(Xc, 1, Bp),        % one-element buf for a Type
  673        jpl_get_primitive_array_region(Type, Array, Index, 1, Bp),
  674        jni_fetch_buffer_value(Bp, 0, Vr, Xc),    % zero-th element
  675        jni_free_buffer(Bp)
  676    ),
  677    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

  686jpl_get_array_elements(ElementType, Array, N, M, Vs) :-
  687    (   (   ElementType = class(_,_)
  688        ;   ElementType = array(_)
  689        )
  690    ->  jpl_get_object_array_elements(Array, N, M, Vs)
  691    ;   jpl_get_primitive_array_elements(ElementType, Array, N, M, Vs)
  692    ).
  693
  694
  695jpl_get_instance_field(boolean, Obj, FieldID, V) :-
  696    jGetBooleanField(Obj, FieldID, V).
  697jpl_get_instance_field(byte, Obj, FieldID, V) :-
  698    jGetByteField(Obj, FieldID, V).
  699jpl_get_instance_field(char, Obj, FieldID, V) :-
  700    jGetCharField(Obj, FieldID, V).
  701jpl_get_instance_field(short, Obj, FieldID, V) :-
  702    jGetShortField(Obj, FieldID, V).
  703jpl_get_instance_field(int, Obj, FieldID, V) :-
  704    jGetIntField(Obj, FieldID, V).
  705jpl_get_instance_field(long, Obj, FieldID, V) :-
  706    jGetLongField(Obj, FieldID, V).
  707jpl_get_instance_field(float, Obj, FieldID, V) :-
  708    jGetFloatField(Obj, FieldID, V).
  709jpl_get_instance_field(double, Obj, FieldID, V) :-
  710    jGetDoubleField(Obj, FieldID, V).
  711jpl_get_instance_field(class(_,_), Obj, FieldID, V) :-
  712    jGetObjectField(Obj, FieldID, V).
  713jpl_get_instance_field(array(_), Obj, FieldID, V) :-
  714    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
  726jpl_get_object_array_elements(Array, Lo, Hi, Vcs) :-
  727    (   Lo =< Hi
  728    ->  Vcs = [Vc|Vcs2],
  729        jGetObjectArrayElement(Array, Lo, Vc),
  730        Next is Lo+1,
  731        jpl_get_object_array_elements(Array, Next, Hi, Vcs2)
  732    ;   Vcs = []
  733    ).
 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
  743jpl_get_primitive_array_elements(ElementType, Array, Lo, Hi, Vcs) :-
  744    Size is Hi-Lo+1,
  745    (   Size == 0
  746    ->  Vcs = []
  747    ;   jni_type_to_xput_code(ElementType, Xc),
  748        jni_alloc_buffer(Xc, Size, Bp),
  749        jpl_get_primitive_array_region(ElementType, Array, Lo, Size, Bp),
  750        jpl_primitive_buffer_to_array(ElementType, Xc, Bp, 0, Size, Vcs),
  751        jni_free_buffer(Bp)
  752    ).
  753
  754
  755jpl_get_primitive_array_region(boolean, Array, Lo, S, I) :-
  756    jGetBooleanArrayRegion(Array, Lo, S, jbuf(I,boolean)).
  757jpl_get_primitive_array_region(byte, Array, Lo, S, I) :-
  758    jGetByteArrayRegion(Array, Lo, S, jbuf(I,byte)).
  759jpl_get_primitive_array_region(char, Array, Lo, S, I) :-
  760    jGetCharArrayRegion(Array, Lo, S, jbuf(I,char)).
  761jpl_get_primitive_array_region(short, Array, Lo, S, I) :-
  762    jGetShortArrayRegion(Array, Lo, S, jbuf(I,short)).
  763jpl_get_primitive_array_region(int, Array, Lo, S, I) :-
  764    jGetIntArrayRegion(Array, Lo, S, jbuf(I,int)).
  765jpl_get_primitive_array_region(long, Array, Lo, S, I) :-
  766    jGetLongArrayRegion(Array, Lo, S, jbuf(I,long)).
  767jpl_get_primitive_array_region(float, Array, Lo, S, I) :-
  768    jGetFloatArrayRegion(Array, Lo, S, jbuf(I,float)).
  769jpl_get_primitive_array_region(double, Array, Lo, S, I) :-
  770    jGetDoubleArrayRegion(Array, Lo, S, jbuf(I,double)).
  771
  772
  773jpl_get_static_field(boolean, Array, FieldID, V) :-
  774    jGetStaticBooleanField(Array, FieldID, V).
  775jpl_get_static_field(byte, Array, FieldID, V) :-
  776    jGetStaticByteField(Array, FieldID, V).
  777jpl_get_static_field(char, Array, FieldID, V) :-
  778    jGetStaticCharField(Array, FieldID, V).
  779jpl_get_static_field(short, Array, FieldID, V) :-
  780    jGetStaticShortField(Array, FieldID, V).
  781jpl_get_static_field(int, Array, FieldID, V) :-
  782    jGetStaticIntField(Array, FieldID, V).
  783jpl_get_static_field(long, Array, FieldID, V) :-
  784    jGetStaticLongField(Array, FieldID, V).
  785jpl_get_static_field(float, Array, FieldID, V) :-
  786    jGetStaticFloatField(Array, FieldID, V).
  787jpl_get_static_field(double, Array, FieldID, V) :-
  788    jGetStaticDoubleField(Array, FieldID, V).
  789jpl_get_static_field(class(_,_), Array, FieldID, V) :-
  790    jGetStaticObjectField(Array, FieldID, V).
  791jpl_get_static_field(array(_), Array, FieldID, V) :-
  792    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.

  812jpl_set(X, Fspec, V) :-
  813    Pred=jpl_set/3,
  814    (   jpl_object_to_type(X, Type)         % the usual case (test is safe if X is var or rubbish)
  815    ->  Obj = X,
  816        catch(
  817            jpl_set_instance(Type, Type, Obj, Fspec, V),    % first 'Type' is for FAI
  818            error(type_error(acyclic,Te),context(jpl_datum_to_type/2,Msg)),
  819            throw_type_error(Pred,acyclic,Te,Msg) % rethrow
  820        )
  821    ;   var(X)
  822    ->  throw_instantiation_error(Pred,em01)
  823    ;   (   atom(X)
  824        ->  (   jpl_classname_to_type(X, Type)          % it's a classname or descriptor...
  825            ->  true
  826            ;   throw_existence_error(Pred,class,X,em02)
  827            )
  828        ;   (   X = class(_,_)                          % it's a class type...
  829            ;   X = array(_)                            % ...or an array type
  830            )
  831        ->  Type = X
  832        ),
  833        (   jpl_type_to_class(Type, ClassObj)      % ...whose Class object is available
  834        ->  true
  835        ;   jpl_type_to_classname(Type, Classname),
  836            throw_existence_error(Pred,class,Classname,em03)
  837        )
  838    ->  catch(
  839            jpl_set_static(Type, ClassObj, Fspec, V),
  840            error(type_error(acyclic,Te),context(jpl_datum_to_type/2,Msg)),
  841            throw_type_error(Pred,acyclic,Te,Msg) % rethrow
  842        )
  843    ;   throw_domain_error(Pred,object_or_class,X,em04)
  844    ).
 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

  857jpl_set_instance(class(_,_), Type, Obj, Fname, V) :-    % a non-array object
  858    Pred=jpl_set/3,
  859    (   atom(Fname)                 % the usual case
  860    ->  true
  861    ;   var(Fname)
  862    ->  throw_instantiation_error(Pred,en01)
  863    ;   throw_type_error(Pred,field_name,Fname,en02)
  864    ),
  865    findall(
  866        z4(I,Mods,FID,Tf),
  867        jpl_field_spec(Type, I, Fname, Mods, FID, Tf),  % public fields of class denoted by Type
  868        Z4s
  869    ),
  870    (   Z4s = []
  871    ->  throw_existence_error(Pred,field,Fname,en03)
  872    ;   Z4s = [z4(I,Mods,FID,Tf)]
  873    ->  (   member(final, Mods)
  874        ->  throw_permission_error(Pred,modify,final_field,Fname,en04)
  875        ;   jpl_datum_to_type(V, Tv)
  876        ->  (   jpl_type_fits_type(Tv, Tf)
  877            ->  (   member(static, Mods)
  878                ->  jpl_object_to_class(Obj, ClassObj),
  879                    jpl_set_static_field(Tf, ClassObj, FID, V)
  880                ;   jpl_set_instance_field(Tf, Obj, FID, V)         % oughta be jpl_set_instance_field?
  881                )
  882            ;   jpl_type_to_nicename(Tf, NNf),
  883                throw_type_error(Pred,NNf,V,en05)
  884            )
  885        ;   throw_type_error(Pred,field_value,V,en06)
  886        )
  887    ;   throw_existence_error(Pred,field,Fname,en07)   % 'existence'? or some other sort of error maybe?
  888    ).
  889
  890jpl_set_instance(array(Type), _, Obj, Fspec, V) :-
  891    Pred=jpl_set/3,
  892    (   is_list(V)                  % a list of array element values
  893    ->  Vs = V
  894    ;   var(V)
  895    ->  throw_instantiation_error(Pred,eo01)
  896    ;   Vs = [V]                    % a single array element value
  897    ),
  898    length(Vs, Iv),
  899    (   var(Fspec)
  900    ->  throw_instantiation_error(Pred,eo02)
  901    ;   integer(Fspec)          % single-element assignment
  902    ->  (   Fspec < 0
  903        ->  throw_domain_error(Pred,array_index,Fspec,eo03)
  904        ;   Iv is 1
  905        ->  N is Fspec
  906        ;   Iv is 0
  907        ->  throw_domain_error(Pred,array_element(Fspec),Vs,eo04)
  908        ;   throw_domain_error(Pred,array_element(Fspec),Vs,eo05)
  909        )
  910    ;   Fspec = N-M             % element-sequence assignment
  911    ->  (   integer(N),
  912            integer(M)
  913        ->  (   N >= 0,
  914                Size is (M-N)+1,
  915                Size >= 0
  916            ->  (   Size == Iv
  917                ->  true
  918                ;   Size < Iv
  919                ->  throw_domain_error(Pred,array_elements(N-M),Vs,eo06)
  920                ;   throw_domain_error(Pred,array_elements(N-M),Vs,eo07)
  921                )
  922            ;   throw_domain_error(Pred,array_index_range,N-M,eo08)
  923            )
  924        ;   throw_type_error(Pred,array_index_range,N-M,eo08)
  925        )
  926    ;   atom(Fspec)
  927    ->  (   Fspec == length
  928        ->  throw_permission_error(Pred,modify,final_field,length,eo09)
  929        ;   throw_existence_error(Pred,field,Fspec,eo10)
  930        )
  931    ;   throw_domain_error(Pred,array_index,Fspec,eo11)
  932    ),
  933    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.

  948jpl_set_static(Type, ClassObj, Fname, V) :-
  949    Pred=jpl_set/3,
  950    (   atom(Fname)                     % the usual case
  951    ->  true
  952    ;   var(Fname)
  953    ->  throw_instantiation_error(Pred,ep01)
  954    ;   throw_type_error(Pred,field_name,Fname,ep02)
  955    ),
  956    findall(  % get all static fields of the denoted class
  957        z4(I,Mods,FID,Tf),
  958        (   jpl_field_spec(Type, I, Fname, Mods, FID, Tf),
  959            member(static, Mods)
  960        ),
  961        Z4s
  962    ),
  963    (   Z4s = []
  964    ->  throw_existence_error(Pred,field,Fname,ep03)
  965    ;   Z4s = [z4(I,Mods,FID,Tf)]       % exactly one synonymous field?
  966    ->  (   member(final, Mods)
  967        ->  throw_permission_error(Pred,modify,final_field,Fname,ep04)
  968        ;   jpl_datum_to_type(V, Tv)
  969        ->  (   jpl_type_fits_type(Tv, Tf)
  970            ->  jpl_set_static_field(Tf, ClassObj, FID, V)
  971            ;   jpl_type_to_nicename(Tf, NNf),
  972                throw_type_error(Pred,NNf,V,ep05)
  973            )
  974        ;   throw_type_error(Pred,field_value,V,ep06)
  975        )
  976    ;   throw_existence_error(Pred,field,Fname,ep07)
  977    ).
 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,_))
  987jpl_set_array(T, A, N, I, Ds) :-
  988    Pred=jpl_set/3,
  989    (   jpl_datums_to_types(Ds, Tds)        % most specialised types of given values
  990    ->  (   jpl_types_fit_type(Tds, T)      % all assignable to element type?
  991        ->  true
  992        ;   throw_type_error(Pred,array(T),Ds,eq01)
  993        )
  994    ;   throw_type_error(Pred,array(T),Ds,eq02)
  995    ),
  996    (   (   T = class(_,_)
  997        ;   T = array(_)                    % array elements are objects
  998        )
  999    ->  (   nth0(J, Ds, D),                 % for each datum
 1000            Nd is N+J,                      % compute array index
 1001            (   D = {Tq}                    % quoted term?
 1002            ->  jni_term_to_jref(Tq, D2)    % convert to a JPL reference to a corresponding org.jpl7.Term object
 1003            ;   D = D2
 1004            ),
 1005            jSetObjectArrayElement(A, Nd, D2),
 1006            fail                            % iterate
 1007        ;   true
 1008        )
 1009    ;   jpl_primitive_type(T)               % array elements are primitive values
 1010    ->  jni_type_to_xput_code(T, Xc),
 1011        jni_alloc_buffer(Xc, I, Bp),        % I-element buf of required primitive type
 1012        jpl_set_array_1(Ds, T, 0, Bp),
 1013        jpl_set_elements(T, A, N, I, Bp),
 1014        jni_free_buffer(Bp)
 1015    ;
 1016        % T is neither a class, nor an array type nor a primitive type
 1017        throw_type_error(Pred,array_element_type,T,eq03)
 1018    ).
 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...

 1029jpl_set_array_1([], _, _, _).
 1030jpl_set_array_1([V|Vs], Tprim, Ib, Bp) :-
 1031    jni_type_to_xput_code(Tprim, Xc),
 1032    jni_stash_buffer_value(Bp, Ib, V, Xc),
 1033    Ibnext is Ib+1,
 1034    jpl_set_array_1(Vs, Tprim, Ibnext, Bp).
 1035
 1036
 1037jpl_set_elements(boolean, Obj, N, I, Bp) :-
 1038    jSetBooleanArrayRegion(Obj, N, I, jbuf(Bp,boolean)).
 1039jpl_set_elements(char, Obj, N, I, Bp) :-
 1040    jSetCharArrayRegion(Obj, N, I, jbuf(Bp,char)).
 1041jpl_set_elements(byte, Obj, N, I, Bp) :-
 1042    jSetByteArrayRegion(Obj, N, I, jbuf(Bp,byte)).
 1043jpl_set_elements(short, Obj, N, I, Bp) :-
 1044    jSetShortArrayRegion(Obj, N, I, jbuf(Bp,short)).
 1045jpl_set_elements(int, Obj, N, I, Bp) :-
 1046    jSetIntArrayRegion(Obj, N, I, jbuf(Bp,int)).
 1047jpl_set_elements(long, Obj, N, I, Bp) :-
 1048    jSetLongArrayRegion(Obj, N, I, jbuf(Bp,long)).
 1049jpl_set_elements(float, Obj, N, I, Bp) :-
 1050    jSetFloatArrayRegion(Obj, N, I, jbuf(Bp,float)).
 1051jpl_set_elements(double, Obj, N, I, Bp) :-
 1052    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)
 1060jpl_set_instance_field(boolean, Obj, FieldID, V) :-
 1061    jSetBooleanField(Obj, FieldID, V).
 1062jpl_set_instance_field(byte, Obj, FieldID, V) :-
 1063    jSetByteField(Obj, FieldID, V).
 1064jpl_set_instance_field(char, Obj, FieldID, V) :-
 1065    jSetCharField(Obj, FieldID, V).
 1066jpl_set_instance_field(short, Obj, FieldID, V) :-
 1067    jSetShortField(Obj, FieldID, V).
 1068jpl_set_instance_field(int, Obj, FieldID, V) :-
 1069    jSetIntField(Obj, FieldID, V).
 1070jpl_set_instance_field(long, Obj, FieldID, V) :-
 1071    jSetLongField(Obj, FieldID, V).
 1072jpl_set_instance_field(float, Obj, FieldID, V) :-
 1073    jSetFloatField(Obj, FieldID, V).
 1074jpl_set_instance_field(double, Obj, FieldID, V) :-
 1075    jSetDoubleField(Obj, FieldID, V).
 1076jpl_set_instance_field(class(_,_), Obj, FieldID, V) :-  % also handles byval term assignments
 1077    (   V = {T}                     % quoted term?
 1078    ->  jni_term_to_jref(T, V2)     % convert to a JPL reference to a corresponding org.jpl7.Term object
 1079    ;   V = V2
 1080    ),
 1081    jSetObjectField(Obj, FieldID, V2).
 1082jpl_set_instance_field(array(_), Obj, FieldID, V) :-
 1083    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).
 1091jpl_set_static_field(boolean, Obj, FieldID, V) :-
 1092    jSetStaticBooleanField(Obj, FieldID, V).
 1093jpl_set_static_field(byte, Obj, FieldID, V) :-
 1094    jSetStaticByteField(Obj, FieldID, V).
 1095jpl_set_static_field(char, Obj, FieldID, V) :-
 1096    jSetStaticCharField(Obj, FieldID, V).
 1097jpl_set_static_field(short, Obj, FieldID, V) :-
 1098    jSetStaticShortField(Obj, FieldID, V).
 1099jpl_set_static_field(int, Obj, FieldID, V) :-
 1100    jSetStaticIntField(Obj, FieldID, V).
 1101jpl_set_static_field(long, Obj, FieldID, V) :-
 1102    jSetStaticLongField(Obj, FieldID, V).
 1103jpl_set_static_field(float, Obj, FieldID, V) :-
 1104    jSetStaticFloatField(Obj, FieldID, V).
 1105jpl_set_static_field(double, Obj, FieldID, V) :-
 1106    jSetStaticDoubleField(Obj, FieldID, V).
 1107jpl_set_static_field(class(_,_), Obj, FieldID, V) :-    % also handles byval term assignments
 1108    (   V = {T}                         % quoted term?
 1109    ->  jni_term_to_jref(T, V2)         % convert to a JPL reference to a corresponding org.jpl7.Term object
 1110    ;   V = V2
 1111    ),
 1112    jSetStaticObjectField(Obj, FieldID, V2).
 1113jpl_set_static_field(array(_), Obj, FieldID, V) :-
 1114    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']
 1122jpl_get_default_jvm_opts(Opts) :-
 1123    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.
 1130jpl_set_default_jvm_opts(Opts) :-
 1131    is_list(Opts),
 1132    length(Opts, N),
 1133    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.

 1142jpl_get_actual_jvm_opts(Opts) :-
 1143    jni_get_actual_jvm_opts(Opts).
 1144
 1145
 1146jpl_assert(Fact) :-
 1147    (   jpl_assert_policy(Fact, yes)
 1148    ->  assert(Fact)
 1149    ;   true
 1150    ).
 1151
 1152
 1153jpl_assert_policy(jpl_field_spec_cache(_,_,_,_,_,_), yes).
 1154jpl_assert_policy(jpl_method_spec_cache(_,_,_,_,_,_,_,_), yes).
 1155jpl_assert_policy(jpl_class_tag_type_cache(_,_), yes).
 1156jpl_assert_policy(jpl_classname_type_cache(_,_), yes).
 1157jpl_assert_policy(jpl_iref_type_cache(_,_), no).   % must correspond to JPL_CACHE_TYPE_OF_REF in jpl.c
 1158jpl_assert_policy(jpl_field_spec_is_cached(_), YN) :-
 1159    jpl_assert_policy(jpl_field_spec_cache(_,_,_,_,_,_), YN).
 1160jpl_assert_policy(jpl_method_spec_is_cached(_), YN) :-
 1161    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()

 1170jpl_tidy_iref_type_cache(Iref) :-
 1171  % write('[decaching types for iref='), write(Iref), write(']'), nl,
 1172    retractall(jpl_iref_type_cache(Iref,_)),
 1173    true.
 1174
 1175jpl_fergus_find_candidate([], Candidate, Candidate, []).
 1176jpl_fergus_find_candidate([X|Xs], Candidate0, Candidate, Rest) :-
 1177    (   jpl_fergus_greater(X, Candidate0)
 1178    ->  Candidate1 = X,
 1179        Rest = [Candidate0|Rest1]
 1180    ;   Candidate1 = Candidate0,
 1181        Rest = [X|Rest1]
 1182    ),
 1183    jpl_fergus_find_candidate(Xs, Candidate1, Candidate, Rest1).
 1184
 1185
 1186jpl_fergus_greater(z5(_,_,_,_,Tps1), z5(_,_,_,_,Tps2)) :-
 1187    jpl_types_fit_types(Tps1, Tps2).
 1188jpl_fergus_greater(z3(_,_,Tps1), z3(_,_,Tps2)) :-
 1189    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
 1200jpl_fergus_is_the_greatest([X|Xs], Greatest) :-
 1201    jpl_fergus_find_candidate(Xs, X, Greatest, Rest),
 1202    forall(
 1203        member(R, Rest),
 1204        jpl_fergus_greater(Greatest, R)
 1205    ).
 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).

 1215jpl_z3s_to_most_specific_z3(Zs, Z) :-
 1216    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)

 1226jpl_z5s_to_most_specific_z5(Zs, Z) :-
 1227    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.6.1'.
 1243jpl_pl_lib_version(VersionString) :-
 1244    jpl_pl_lib_version(Major, Minor, Patch, Status),
 1245    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.
 1262jpl_pl_lib_version(7, 6, 1, stable).  % 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)
 1291jpl_java_lib_version(V) :-
 1292    jpl_call('org.jpl7.JPL', version_string, [], V).
 jpl_pl_lib_path(-Path:atom)
 1297jpl_pl_lib_path(Path) :-
 1298    module_property(jpl, file(Path)).
 jpl_c_lib_path(-Path:atom)
 1303jpl_c_lib_path(Path) :-
 1304    shlib:current_library(_, _, Path, jpl, _),
 1305    !.
 jpl_java_lib_path(-Path:atom)
 1310jpl_java_lib_path(Path) :-
 1311    jpl_call('org.jpl7.JPL', jarPath, [], Path).
 1312
 1313
 1314% jpl_type_alfa(0'$) -->        % presumably not allowed
 1315%   "$".                        % given the "inner class" syntax?
 1316
 1317jpl_type_alfa(0'_) -->
 1318    "_",
 1319    !.
 1320jpl_type_alfa(C) -->
 1321    [C], { C>=0'a, C=<0'z },
 1322    !.
 1323jpl_type_alfa(C) -->
 1324    [C], { C>=0'A, C=<0'Z }.
 1325
 1326
 1327jpl_type_alfa_num(C) -->
 1328    jpl_type_alfa(C),
 1329    !.
 1330jpl_type_alfa_num(C) -->
 1331    [C], { C>=0'0, C=<0'9 }.
 1332
 1333
 1334jpl_type_array_classname(array(T)) -->
 1335    "[", jpl_type_classname_2(T).
 1336
 1337
 1338jpl_type_array_descriptor(array(T)) -->
 1339    "[", jpl_type_descriptor_1(T).
 1340
 1341
 1342jpl_type_bare_class_descriptor(class(Ps,Cs)) -->
 1343    jpl_type_slashed_package_parts(Ps), jpl_type_class_parts(Cs).
 1344
 1345
 1346jpl_type_bare_classname(class(Ps,Cs)) -->
 1347    jpl_type_dotted_package_parts(Ps), jpl_type_class_parts(Cs).
 1348
 1349
 1350jpl_type_class_descriptor(class(Ps,Cs)) -->
 1351    "L", jpl_type_bare_class_descriptor(class(Ps,Cs)), ";".
 1352
 1353
 1354jpl_type_class_part(N) -->
 1355    jpl_type_id(N).
 1356
 1357
 1358jpl_type_class_parts([C|Cs]) -->
 1359    jpl_type_class_part(C), jpl_type_inner_class_parts(Cs).
 1360
 1361
 1362jpl_type_classname_1(T) -->
 1363    jpl_type_bare_classname(T),
 1364    !.
 1365jpl_type_classname_1(T) -->
 1366    jpl_type_array_classname(T),
 1367    !.
 1368jpl_type_classname_1(T) -->
 1369    jpl_type_primitive(T).
 1370
 1371
 1372jpl_type_classname_2(T) -->
 1373    jpl_type_delimited_classname(T).
 1374jpl_type_classname_2(T) -->
 1375    jpl_type_array_classname(T).
 1376jpl_type_classname_2(T) -->
 1377    jpl_type_primitive(T).
 1378
 1379
 1380
 1381jpl_type_delimited_classname(Class) -->
 1382    "L", jpl_type_bare_classname(Class), ";".
 1383
 1384
 1385
 1386jpl_type_descriptor_1(T) -->
 1387    jpl_type_primitive(T),
 1388    !.
 1389jpl_type_descriptor_1(T) -->
 1390    jpl_type_class_descriptor(T),
 1391    !.
 1392jpl_type_descriptor_1(T) -->
 1393    jpl_type_array_descriptor(T),
 1394    !.
 1395jpl_type_descriptor_1(T) -->
 1396    jpl_type_method_descriptor(T).
 1397
 1398
 1399
 1400jpl_type_dotted_package_parts([P|Ps]) -->
 1401    jpl_type_package_part(P), ".", !, jpl_type_dotted_package_parts(Ps).
 1402jpl_type_dotted_package_parts([]) -->
 1403    [].
 1404
 1405
 1406
 1407jpl_type_findclassname(T) -->
 1408    jpl_type_bare_class_descriptor(T).
 1409jpl_type_findclassname(T) -->
 1410    jpl_type_array_descriptor(T).
 1411
 1412
 1413
 1414jpl_type_id(A) -->
 1415    { nonvar(A) -> atom_codes(A,[C|Cs]) ; true },
 1416    jpl_type_alfa(C), jpl_type_id_rest(Cs),
 1417    { atom_codes(A, [C|Cs]) }.
 1418
 1419
 1420
 1421jpl_type_id_rest([C|Cs]) -->
 1422    jpl_type_alfa_num(C), !, jpl_type_id_rest(Cs).
 1423jpl_type_id_rest([]) -->
 1424    [].
 1425
 1426
 1427
 1428jpl_type_id_v2(A) -->                   % inner class name parts (empirically)
 1429    { nonvar(A) -> atom_codes(A,Cs) ; true },
 1430    jpl_type_id_rest(Cs),
 1431    { atom_codes(A, Cs) }.
 1432
 1433
 1434
 1435jpl_type_inner_class_part(N) -->
 1436    jpl_type_id_v2(N).
 1437
 1438
 1439
 1440jpl_type_inner_class_parts([C|Cs]) -->
 1441    "$", jpl_type_inner_class_part(C), !, jpl_type_inner_class_parts(Cs).
 1442jpl_type_inner_class_parts([]) -->
 1443    [].
 1444
 1445
 1446
 1447jpl_type_method_descriptor(method(Ts,T)) -->
 1448    "(", jpl_type_method_descriptor_args(Ts), ")", jpl_type_method_descriptor_return(T).
 1449
 1450
 1451
 1452jpl_type_method_descriptor_args([T|Ts]) -->
 1453    jpl_type_descriptor_1(T), !, jpl_type_method_descriptor_args(Ts).
 1454jpl_type_method_descriptor_args([]) -->
 1455    [].
 1456
 1457
 1458
 1459jpl_type_method_descriptor_return(T) -->
 1460    jpl_type_void(T).
 1461jpl_type_method_descriptor_return(T) -->
 1462    jpl_type_descriptor_1(T).
 1463
 1464
 1465
 1466jpl_type_package_part(N) -->
 1467    jpl_type_id(N).
 1468
 1469
 1470
 1471jpl_type_primitive(boolean) -->
 1472    "Z",
 1473    !.
 1474jpl_type_primitive(byte) -->
 1475    "B",
 1476    !.
 1477jpl_type_primitive(char) -->
 1478    "C",
 1479    !.
 1480jpl_type_primitive(short) -->
 1481    "S",
 1482    !.
 1483jpl_type_primitive(int) -->
 1484    "I",
 1485    !.
 1486jpl_type_primitive(long) -->
 1487    "J",
 1488    !.
 1489jpl_type_primitive(float) -->
 1490    "F",
 1491    !.
 1492jpl_type_primitive(double) -->
 1493    "D".
 1494
 1495
 1496
 1497jpl_type_slashed_package_parts([P|Ps]) -->
 1498    jpl_type_package_part(P), "/", !, jpl_type_slashed_package_parts(Ps).
 1499jpl_type_slashed_package_parts([]) -->
 1500    [].
 1501
 1502
 1503
 1504jpl_type_void(void) -->
 1505    "V".
 jCallBooleanMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rbool:boolean)
 1511jCallBooleanMethod(Obj, MethodID, Types, Params, Rbool) :-
 1512    jni_params_put(Params, Types, ParamBuf),
 1513    jni_func(39, Obj, MethodID, ParamBuf, Rbool).
 jCallByteMethod(+Obj:jref, +MethodID:methodId, +Types, +Params:list(datum), -Rbyte:byte)
 1519jCallByteMethod(Obj, MethodID, Types, Params, Rbyte) :-
 1520    jni_params_put(Params, Types, ParamBuf),
 1521    jni_func(42, Obj, MethodID, ParamBuf, Rbyte).
 jCallCharMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rchar:char)
 1527jCallCharMethod(Obj, MethodID, Types, Params, Rchar) :-
 1528    jni_params_put(Params, Types, ParamBuf),
 1529    jni_func(45, Obj, MethodID, ParamBuf, Rchar).
 jCallDoubleMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rdouble:double)
 1534jCallDoubleMethod(Obj, MethodID, Types, Params, Rdouble) :-
 1535    jni_params_put(Params, Types, ParamBuf),
 1536    jni_func(60, Obj, MethodID, ParamBuf, Rdouble).
 jCallFloatMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rfloat:float)
 1541jCallFloatMethod(Obj, MethodID, Types, Params, Rfloat) :-
 1542    jni_params_put(Params, Types, ParamBuf),
 1543    jni_func(57, Obj, MethodID, ParamBuf, Rfloat).
 jCallIntMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rint:int)
 1548jCallIntMethod(Obj, MethodID, Types, Params, Rint) :-
 1549    jni_params_put(Params, Types, ParamBuf),
 1550    jni_func(51, Obj, MethodID, ParamBuf, Rint).
 jCallLongMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rlong:long)
 1555jCallLongMethod(Obj, MethodID, Types, Params, Rlong) :-
 1556    jni_params_put(Params, Types, ParamBuf),
 1557    jni_func(54, Obj, MethodID, ParamBuf, Rlong).
 jCallObjectMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Robj:jref)
 1562jCallObjectMethod(Obj, MethodID, Types, Params, Robj) :-
 1563    jni_params_put(Params, Types, ParamBuf),
 1564    jni_func(36, Obj, MethodID, ParamBuf, Robj).
 jCallShortMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rshort:short)
 1569jCallShortMethod(Obj, MethodID, Types, Params, Rshort) :-
 1570    jni_params_put(Params, Types, ParamBuf),
 1571    jni_func(48, Obj, MethodID, ParamBuf, Rshort).
 jCallStaticBooleanMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rbool:boolean)
 1576jCallStaticBooleanMethod(Class, MethodID, Types, Params, Rbool) :-
 1577    jni_params_put(Params, Types, ParamBuf),
 1578    jni_func(119, Class, MethodID, ParamBuf, Rbool).
 jCallStaticByteMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rbyte:byte)
 1583jCallStaticByteMethod(Class, MethodID, Types, Params, Rbyte) :-
 1584    jni_params_put(Params, Types, ParamBuf),
 1585    jni_func(122, Class, MethodID, ParamBuf, Rbyte).
 jCallStaticCharMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rchar:char)
 1590jCallStaticCharMethod(Class, MethodID, Types, Params, Rchar) :-
 1591    jni_params_put(Params, Types, ParamBuf),
 1592    jni_func(125, Class, MethodID, ParamBuf, Rchar).
 jCallStaticDoubleMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rdouble:double)
 1597jCallStaticDoubleMethod(Class, MethodID, Types, Params, Rdouble) :-
 1598    jni_params_put(Params, Types, ParamBuf),
 1599    jni_func(140, Class, MethodID, ParamBuf, Rdouble).
 jCallStaticFloatMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rfloat:float)
 1604jCallStaticFloatMethod(Class, MethodID, Types, Params, Rfloat) :-
 1605    jni_params_put(Params, Types, ParamBuf),
 1606    jni_func(137, Class, MethodID, ParamBuf, Rfloat).
 jCallStaticIntMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rint:int)
 1611jCallStaticIntMethod(Class, MethodID, Types, Params, Rint) :-
 1612    jni_params_put(Params, Types, ParamBuf),
 1613    jni_func(131, Class, MethodID, ParamBuf, Rint).
 jCallStaticLongMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rlong:long)
 1618jCallStaticLongMethod(Class, MethodID, Types, Params, Rlong) :-
 1619    jni_params_put(Params, Types, ParamBuf),
 1620    jni_func(134, Class, MethodID, ParamBuf, Rlong).
 jCallStaticObjectMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Robj:jref)
 1625jCallStaticObjectMethod(Class, MethodID, Types, Params, Robj) :-
 1626    jni_params_put(Params, Types, ParamBuf),
 1627    jni_func(116, Class, MethodID, ParamBuf, Robj).
 jCallStaticShortMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Rshort:short)
 1632jCallStaticShortMethod(Class, MethodID, Types, Params, Rshort) :-
 1633    jni_params_put(Params, Types, ParamBuf),
 1634    jni_func(128, Class, MethodID, ParamBuf, Rshort).
 jCallStaticVoidMethod(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum))
 1639jCallStaticVoidMethod(Class, MethodID, Types, Params) :-
 1640    jni_params_put(Params, Types, ParamBuf),
 1641    jni_void(143, Class, MethodID, ParamBuf).
 jCallVoidMethod(+Obj:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum))
 1646jCallVoidMethod(Obj, MethodID, Types, Params) :-
 1647    jni_params_put(Params, Types, ParamBuf),
 1648    jni_void(63, Obj, MethodID, ParamBuf).
 jFindClass(+ClassName:findclassname, -Class:jref)
 1653jFindClass(ClassName, Class) :-
 1654    jni_func(6, ClassName, Class).
 jGetArrayLength(+Array:jref, -Size:int)
 1659jGetArrayLength(Array, Size) :-
 1660    jni_func(171, Array, Size).
 jGetBooleanArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:boolean_buf)
 1665jGetBooleanArrayRegion(Array, Start, Len, Buf) :-
 1666    jni_void(199, Array, Start, Len, Buf).
 jGetBooleanField(+Obj:jref, +FieldID:fieldId, -Rbool:boolean)
 1671jGetBooleanField(Obj, FieldID, Rbool) :-
 1672    jni_func(96, Obj, FieldID, Rbool).
 jGetByteArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:byte_buf)
 1677jGetByteArrayRegion(Array, Start, Len, Buf) :-
 1678    jni_void(200, Array, Start, Len, Buf).
 jGetByteField(+Obj:jref, +FieldID:fieldId, -Rbyte:byte)
 1683jGetByteField(Obj, FieldID, Rbyte) :-
 1684    jni_func(97, Obj, FieldID, Rbyte).
 jGetCharArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:char_buf)
 1689jGetCharArrayRegion(Array, Start, Len, Buf) :-
 1690    jni_void(201, Array, Start, Len, Buf).
 jGetCharField(+Obj:jref, +FieldID:fieldId, -Rchar:char)
 1695jGetCharField(Obj, FieldID, Rchar) :-
 1696    jni_func(98, Obj, FieldID, Rchar).
 jGetDoubleArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:double_buf)
 1701jGetDoubleArrayRegion(Array, Start, Len, Buf) :-
 1702    jni_void(206, Array, Start, Len, Buf).
 jGetDoubleField(+Obj:jref, +FieldID:fieldId, -Rdouble:double)
 1707jGetDoubleField(Obj, FieldID, Rdouble) :-
 1708    jni_func(103, Obj, FieldID, Rdouble).
 jGetFieldID(+Class:jref, +Name:fieldName, +Type:type, -FieldID:fieldId)
 1713jGetFieldID(Class, Name, Type, FieldID) :-
 1714    jpl_type_to_descriptor(Type, TD),
 1715    jni_func(94, Class, Name, TD, FieldID).
 jGetFloatArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:float_buf)
 1720jGetFloatArrayRegion(Array, Start, Len, Buf) :-
 1721    jni_void(205, Array, Start, Len, Buf).
 jGetFloatField(+Obj:jref, +FieldID:fieldId, -Rfloat:float)
 1726jGetFloatField(Obj, FieldID, Rfloat) :-
 1727    jni_func(102, Obj, FieldID, Rfloat).
 jGetIntArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:int_buf)
 1732jGetIntArrayRegion(Array, Start, Len, Buf) :-
 1733    jni_void(203, Array, Start, Len, Buf).
 jGetIntField(+Obj:jref, +FieldID:fieldId, -Rint:int)
 1738jGetIntField(Obj, FieldID, Rint) :-
 1739    jni_func(100, Obj, FieldID, Rint).
 jGetLongArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:long_buf)
 1744jGetLongArrayRegion(Array, Start, Len, Buf) :-
 1745    jni_void(204, Array, Start, Len, Buf).
 jGetLongField(+Obj:jref, +FieldID:fieldId, -Rlong:long)
 1750jGetLongField(Obj, FieldID, Rlong) :-
 1751    jni_func(101, Obj, FieldID, Rlong).
 jGetMethodID(+Class:jref, +Name:atom, +Type:type, -MethodID:methodId)
 1756jGetMethodID(Class, Name, Type, MethodID) :-
 1757    jpl_type_to_descriptor(Type, TD),
 1758    jni_func(33, Class, Name, TD, MethodID).
 jGetObjectArrayElement(+Array:jref, +Index:int, -Obj:jref)
 1763jGetObjectArrayElement(Array, Index, Obj) :-
 1764    jni_func(173, Array, Index, Obj).
 jGetObjectClass(+Object:jref, -Class:jref)
 1769jGetObjectClass(Object, Class) :-
 1770    jni_func(31, Object, Class).
 jGetObjectField(+Obj:jref, +FieldID:fieldId, -RObj:jref)
 1775jGetObjectField(Obj, FieldID, Robj) :-
 1776    jni_func(95, Obj, FieldID, Robj).
 jGetShortArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:short_buf)
 1781jGetShortArrayRegion(Array, Start, Len, Buf) :-
 1782    jni_void(202, Array, Start, Len, Buf).
 jGetShortField(+Obj:jref, +FieldID:fieldId, -Rshort:short)
 1787jGetShortField(Obj, FieldID, Rshort) :-
 1788    jni_func(99, Obj, FieldID, Rshort).
 jGetStaticBooleanField(+Class:jref, +FieldID:fieldId, -Rbool:boolean)
 1793jGetStaticBooleanField(Class, FieldID, Rbool) :-
 1794    jni_func(146, Class, FieldID, Rbool).
 jGetStaticByteField(+Class:jref, +FieldID:fieldId, -Rbyte:byte)
 1799jGetStaticByteField(Class, FieldID, Rbyte) :-
 1800    jni_func(147, Class, FieldID, Rbyte).
 jGetStaticCharField(+Class:jref, +FieldID:fieldId, -Rchar:char)
 1805jGetStaticCharField(Class, FieldID, Rchar) :-
 1806    jni_func(148, Class, FieldID, Rchar).
 jGetStaticDoubleField(+Class:jref, +FieldID:fieldId, -Rdouble:double)
 1811jGetStaticDoubleField(Class, FieldID, Rdouble) :-
 1812    jni_func(153, Class, FieldID, Rdouble).
 jGetStaticFieldID(+Class:jref, +Name:fieldName, +Type:type, -FieldID:fieldId)
 1817jGetStaticFieldID(Class, Name, Type, FieldID) :-
 1818    jpl_type_to_descriptor(Type, TD),               % cache this?
 1819    jni_func(144, Class, Name, TD, FieldID).
 jGetStaticFloatField(+Class:jref, +FieldID:fieldId, -Rfloat:float)
 1824jGetStaticFloatField(Class, FieldID, Rfloat) :-
 1825    jni_func(152, Class, FieldID, Rfloat).
 jGetStaticIntField(+Class:jref, +FieldID:fieldId, -Rint:int)
 1830jGetStaticIntField(Class, FieldID, Rint) :-
 1831    jni_func(150, Class, FieldID, Rint).
 jGetStaticLongField(+Class:jref, +FieldID:fieldId, -Rlong:long)
 1836jGetStaticLongField(Class, FieldID, Rlong) :-
 1837    jni_func(151, Class, FieldID, Rlong).
 jGetStaticMethodID(+Class:jref, +Name:methodName, +Type:type, -MethodID:methodId)
 1842jGetStaticMethodID(Class, Name, Type, MethodID) :-
 1843    jpl_type_to_descriptor(Type, TD),
 1844    jni_func(113, Class, Name, TD, MethodID).
 jGetStaticObjectField(+Class:jref, +FieldID:fieldId, -RObj:jref)
 1849jGetStaticObjectField(Class, FieldID, Robj) :-
 1850    jni_func(145, Class, FieldID, Robj).
 jGetStaticShortField(+Class:jref, +FieldID:fieldId, -Rshort:short)
 1855jGetStaticShortField(Class, FieldID, Rshort) :-
 1856    jni_func(149, Class, FieldID, Rshort).
 jGetSuperclass(+Class1:jref, -Class2:jref)
 1861jGetSuperclass(Class1, Class2) :-
 1862    jni_func(10, Class1, Class2).
 jIsAssignableFrom(+Class1:jref, +Class2:jref)
 1867jIsAssignableFrom(Class1, Class2) :-
 1868    jni_func(11, Class1, Class2, @(true)).
 jNewBooleanArray(+Length:int, -Array:jref)
 1873jNewBooleanArray(Length, Array) :-
 1874    jni_func(175, Length, Array).
 jNewByteArray(+Length:int, -Array:jref)
 1879jNewByteArray(Length, Array) :-
 1880    jni_func(176, Length, Array).
 jNewCharArray(+Length:int, -Array:jref)
 1885jNewCharArray(Length, Array) :-
 1886    jni_func(177, Length, Array).
 jNewDoubleArray(+Length:int, -Array:jref)
 1891jNewDoubleArray(Length, Array) :-
 1892    jni_func(182, Length, Array).
 jNewFloatArray(+Length:int, -Array:jref)
 1897jNewFloatArray(Length, Array) :-
 1898    jni_func(181, Length, Array).
 jNewIntArray(+Length:int, -Array:jref)
 1903jNewIntArray(Length, Array) :-
 1904    jni_func(179, Length, Array).
 jNewLongArray(+Length:int, -Array:jref)
 1909jNewLongArray(Length, Array) :-
 1910    jni_func(180, Length, Array).
 jNewObject(+Class:jref, +MethodID:methodId, +Types:list(type), +Params:list(datum), -Obj:jref)
 1915jNewObject(Class, MethodID, Types, Params, Obj) :-
 1916    jni_params_put(Params, Types, ParamBuf),
 1917    jni_func(30, Class, MethodID, ParamBuf, Obj).
 jNewObjectArray(+Len:int, +Class:jref, +InitVal:jref, -Array:jref)
 1922jNewObjectArray(Len, Class, InitVal, Array) :-
 1923    jni_func(172, Len, Class, InitVal, Array).
 jNewShortArray(+Length:int, -Array:jref)
 1928jNewShortArray(Length, Array) :-
 1929    jni_func(178, Length, Array).
 jSetBooleanArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:boolean_buf)
 1934jSetBooleanArrayRegion(Array, Start, Len, Buf) :-
 1935    jni_void(207, Array, Start, Len, Buf).
 jSetBooleanField(+Obj:jref, +FieldID:fieldId, +Rbool:boolean)
 1940jSetBooleanField(Obj, FieldID, Rbool) :-
 1941    jni_void(105, Obj, FieldID, Rbool).
 jSetByteArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:byte_buf)
 1946jSetByteArrayRegion(Array, Start, Len, Buf) :-
 1947    jni_void(208, Array, Start, Len, Buf).
 jSetByteField(+Obj:jref, +FieldID:fieldId, +Rbyte:byte)
 1952jSetByteField(Obj, FieldID, Rbyte) :-
 1953    jni_void(106, Obj, FieldID, Rbyte).
 jSetCharArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:char_buf)
 1958jSetCharArrayRegion(Array, Start, Len, Buf) :-
 1959    jni_void(209, Array, Start, Len, Buf).
 jSetCharField(+Obj:jref, +FieldID:fieldId, +Rchar:char)
 1964jSetCharField(Obj, FieldID, Rchar) :-
 1965    jni_void(107, Obj, FieldID, Rchar).
 jSetDoubleArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:double_buf)
 1970jSetDoubleArrayRegion(Array, Start, Len, Buf) :-
 1971    jni_void(214, Array, Start, Len, Buf).
 jSetDoubleField(+Obj:jref, +FieldID:fieldId, +Rdouble:double)
 1976jSetDoubleField(Obj, FieldID, Rdouble) :-
 1977    jni_void(112, Obj, FieldID, Rdouble).
 jSetFloatArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:float_buf)
 1982jSetFloatArrayRegion(Array, Start, Len, Buf) :-
 1983    jni_void(213, Array, Start, Len, Buf).
 jSetFloatField(+Obj:jref, +FieldID:fieldId, +Rfloat:float)
 1988jSetFloatField(Obj, FieldID, Rfloat) :-
 1989    jni_void(111, Obj, FieldID, Rfloat).
 jSetIntArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:int_buf)
 1994jSetIntArrayRegion(Array, Start, Len, Buf) :-
 1995    jni_void(211, Array, Start, Len, Buf).
 jSetIntField(+Obj:jref, +FieldID:fieldId, +Rint:int)
 2000jSetIntField(Obj, FieldID, Rint) :-
 2001    jni_void(109, Obj, FieldID, Rint).
 jSetLongArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:long_buf)
 2006jSetLongArrayRegion(Array, Start, Len, Buf) :-
 2007    jni_void(212, Array, Start, Len, Buf).
 jSetLongField(+Obj:jref, +FieldID:fieldId, +Rlong:long)
 2012jSetLongField(Obj, FieldID, Rlong) :-
 2013    jni_void(110, Obj, FieldID, Rlong).
 jSetObjectArrayElement(+Array:jref, +Index:int, +Obj:jref)
 2018jSetObjectArrayElement(Array, Index, Obj) :-
 2019    jni_void(174, Array, Index, Obj).
 jSetObjectField(+Obj:jref, +FieldID:fieldId, +RObj:jref)
 2024jSetObjectField(Obj, FieldID, Robj) :-
 2025    jni_void(104, Obj, FieldID, Robj).
 jSetShortArrayRegion(+Array:jref, +Start:int, +Len:int, +Buf:short_buf)
 2030jSetShortArrayRegion(Array, Start, Len, Buf) :-
 2031    jni_void(210, Array, Start, Len, Buf).
 jSetShortField(+Obj:jref, +FieldID:fieldId, +Rshort:short)
 2036jSetShortField(Obj, FieldID, Rshort) :-
 2037    jni_void(108, Obj, FieldID, Rshort).
 jSetStaticBooleanField(+Class:jref, +FieldID:fieldId, +Rbool:boolean)
 2042jSetStaticBooleanField(Class, FieldID, Rbool) :-
 2043    jni_void(155, Class, FieldID, Rbool).
 jSetStaticByteField(+Class:jref, +FieldID:fieldId, +Rbyte:byte)
 2048jSetStaticByteField(Class, FieldID, Rbyte) :-
 2049    jni_void(156, Class, FieldID, Rbyte).
 jSetStaticCharField(+Class:jref, +FieldID:fieldId, +Rchar:char)
 2054jSetStaticCharField(Class, FieldID, Rchar) :-
 2055    jni_void(157, Class, FieldID, Rchar).
 jSetStaticDoubleField(+Class:jref, +FieldID:fieldId, +Rdouble:double)
 2060jSetStaticDoubleField(Class, FieldID, Rdouble) :-
 2061    jni_void(162, Class, FieldID, Rdouble).
 jSetStaticFloatField(+Class:jref, +FieldID:fieldId, +Rfloat:float)
 2066jSetStaticFloatField(Class, FieldID, Rfloat) :-
 2067    jni_void(161, Class, FieldID, Rfloat).
 jSetStaticIntField(+Class:jref, +FieldID:fieldId, +Rint:int)
 2072jSetStaticIntField(Class, FieldID, Rint) :-
 2073    jni_void(159, Class, FieldID, Rint).
 jSetStaticLongField(+Class:jref, +FieldID:fieldId, +Rlong)
 2078jSetStaticLongField(Class, FieldID, Rlong) :-
 2079    jni_void(160, Class, FieldID, Rlong).
 jSetStaticObjectField(+Class:jref, +FieldID:fieldId, +Robj:jref)
 2084jSetStaticObjectField(Class, FieldID, Robj) :-
 2085    jni_void(154, Class, FieldID, Robj).
 jSetStaticShortField(+Class:jref, +FieldID:fieldId, +Rshort:short)
 2090jSetStaticShortField(Class, FieldID, Rshort) :-
 2091    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).
 2101jni_params_put(As, Ts, ParamBuf)     :-
 2102    jni_ensure_jvm,                     % in case e.g. NewStringUTF() is called
 2103    length(As, N),
 2104    jni_type_to_xput_code(jvalue, Xc), % Xc will be 15
 2105    jni_alloc_buffer(Xc, N, ParamBuf),
 2106    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

 2125jni_params_put_1([], _, [], _).
 2126jni_params_put_1([A|As], N, [Tjni|Ts], ParamBuf) :-     % type checking?
 2127    (   jni_type_to_xput_code(Tjni, Xc)
 2128    ->  (   A = {Term}                                  % a quoted general term?
 2129        ->  jni_term_to_jref(Term, Ax)                  % convert it to a @(Tag) ref to a new Term instance
 2130        ;   A = Ax
 2131        ),
 2132        jni_param_put(N, Xc, Ax, ParamBuf)              % foreign
 2133    ;   fail                                            % oughta raise an exception?
 2134    ),
 2135    N2 is N+1,
 2136    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)

 2146jni_type_to_xput_code(boolean,      1).     % JNI_XPUT_BOOLEAN
 2147jni_type_to_xput_code(byte,         2).     % JNI_XPUT_BYTE
 2148jni_type_to_xput_code(char,         3).     % JNI_XPUT_CHAR
 2149jni_type_to_xput_code(short,        4).     % JNI_XPUT_SHORT
 2150jni_type_to_xput_code(int,          5).     % JNI_XPUT_INT
 2151jni_type_to_xput_code(long,         6).     % JNI_XPUT_LONG
 2152jni_type_to_xput_code(float,        7).     % JNI_XPUT_FLOAT
 2153jni_type_to_xput_code(double,       8).     % JNI_XPUT_DOUBLE
 2154jni_type_to_xput_code(class(_,_),   12).    % JNI_XPUT_REF
 2155jni_type_to_xput_code(array(_),     12).    % JNI_XPUT_REF
 2156jni_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?
 2163jpl_class_to_constructor_array(Cx, Ma) :-
 2164    jpl_classname_to_class('java.lang.Class', CC),      % cacheable?
 2165    jGetMethodID( CC, getConstructors, method([],array(class([java,lang,reflect],['Constructor']))), MID), % cacheable?
 2166    jCallObjectMethod(Cx, MID, [], [], Ma).
 jpl_class_to_constructors(+Class:jref, -Methods:list(jref))
 2171jpl_class_to_constructors(Cx, Ms) :-
 2172    jpl_class_to_constructor_array(Cx, Ma),
 2173    jpl_object_array_to_list(Ma, Ms).
 jpl_class_to_field_array(+Class:jref, -FieldArray:jref)
 2178jpl_class_to_field_array(Cx, Fa) :-
 2179    jpl_classname_to_class('java.lang.Class', CC),      % cacheable?
 2180    jGetMethodID(CC, getFields, method([],array(class([java,lang,reflect],['Field']))), MID),  % cacheable?
 2181    jCallObjectMethod(Cx, MID, [], [], Fa).
 jpl_class_to_fields(+Class:jref, -Fields:list(jref))
NB do this in Java (ditto for methods)?
 2188jpl_class_to_fields(C, Fs) :-
 2189    jpl_class_to_field_array(C, Fa),
 2190    jpl_object_array_to_list(Fa, Fs).
 jpl_class_to_method_array(+Class:jref, -MethodArray:jref)
NB migrate into foreign code for efficiency?
 2197jpl_class_to_method_array(Cx, Ma) :-
 2198    jpl_classname_to_class('java.lang.Class', CC),      % cacheable?
 2199    jGetMethodID(CC, getMethods, method([],array(class([java,lang,reflect],['Method']))), MID),  % cacheable?
 2200    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)?

 2209jpl_class_to_methods(Cx, Ms) :-
 2210    jpl_class_to_method_array(Cx, Ma),
 2211    jpl_object_array_to_list(Ma, Ms).
 jpl_constructor_to_modifiers(+Method, -Modifiers)
NB migrate into foreign code for efficiency?
 2218jpl_constructor_to_modifiers(X, Ms) :-
 2219    jpl_classname_to_class('java.lang.reflect.Constructor', Cx),   % cached?
 2220    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>'.
 2228jpl_constructor_to_name(_X, '<init>').
 jpl_constructor_to_parameter_types(+Method:jref, -ParameterTypes:list(type))
NB migrate to foreign code for efficiency?
 2235jpl_constructor_to_parameter_types(X, Tfps) :-
 2236    jpl_classname_to_class('java.lang.reflect.Constructor', Cx),   % cached?
 2237    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'.
 2245jpl_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.
 2252jpl_field_spec(T, I, N, Mods, MID, Tf) :-
 2253    (   jpl_field_spec_is_cached(T)
 2254    ->  jpl_field_spec_cache(T, I, N, Mods, MID, Tf)
 2255    ;   jpl_type_to_class(T, C),
 2256        jpl_class_to_fields(C, Fs),
 2257        (   T = array(_BaseType)    % regardless of base type...
 2258        ->  Tci = array(_)          % ...the "cache index" type is this
 2259        ;   Tci = T
 2260        ),
 2261        jpl_field_spec_1(C, Tci, Fs),
 2262        jpl_assert(jpl_field_spec_is_cached(Tci)),
 2263        jpl_field_spec_cache(Tci, I, N, Mods, MID, Tf)
 2264    ).
 2265
 2266
 2267jpl_field_spec_1(C, Tci, Fs) :-
 2268    (   nth1(I, Fs, F),
 2269        jpl_field_to_name(F, N),
 2270        jpl_field_to_modifiers(F, Mods),
 2271        jpl_field_to_type(F, Tf),
 2272        (   member(static, Mods)
 2273        ->  jGetStaticFieldID(C, N, Tf, MID)
 2274        ;   jGetFieldID(C, N, Tf, MID)
 2275        ),
 2276        jpl_assert(jpl_field_spec_cache(Tci,I,N,Mods,MID,Tf)),
 2277        fail
 2278    ;   true
 2279    ).
 2280
 2281
 2282:- dynamic jpl_field_spec_cache/6.      % document this...
 2283
 2284
 2285:- dynamic jpl_field_spec_is_cached/1.  % document this...
 jpl_field_to_modifiers(+Field:jref, -Modifiers:ordset(modifier))
 2290jpl_field_to_modifiers(F, Ms) :-
 2291    jpl_classname_to_class('java.lang.reflect.Field', Cf),
 2292    jpl_method_to_modifiers_1(F, Cf, Ms).
 jpl_field_to_name(+Field:jref, -Name:atom)
 2297jpl_field_to_name(F, N) :-
 2298    jpl_classname_to_class('java.lang.reflect.Field', Cf),
 2299    jpl_member_to_name_1(F, Cf, N).
 jpl_field_to_type(+Field:jref, -Type:type)
 2304jpl_field_to_type(F, Tf) :-
 2305    jpl_classname_to_class('java.lang.reflect.Field', Cf),
 2306    jGetMethodID(Cf, getType, method([],class([java,lang],['Class'])), MID),
 2307    jCallObjectMethod(F, MID, [], [], Cr),
 2308    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.
 2316jpl_method_spec(T, I, N, A, Mods, MID, Tr, Tfps) :-
 2317    (   jpl_method_spec_is_cached(T)
 2318    ->  jpl_method_spec_cache(T, I, N, A, Mods, MID, Tr, Tfps)
 2319    ;   jpl_type_to_class(T, C),
 2320        jpl_class_to_constructors(C, Xs),
 2321        jpl_class_to_methods(C, Ms),
 2322        (   T = array(_BaseType)    % regardless of base type...
 2323        ->  Tci = array(_)          % ...the "cache index" type is this
 2324        ;   Tci = T
 2325        ),
 2326        jpl_method_spec_1(C, Tci, Xs, Ms),
 2327        jpl_assert(jpl_method_spec_is_cached(Tci)),
 2328        jpl_method_spec_cache(Tci, I, N, A, Mods, MID, Tr, Tfps)
 2329    ).
 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.
 2336jpl_method_spec_1(C, Tci, Xs, Ms) :-
 2337    (   (   nth1(I, Xs, X),     % generate constructors, numbered from 1
 2338            jpl_constructor_to_name(X, N),
 2339            jpl_constructor_to_modifiers(X, Mods),
 2340            jpl_constructor_to_return_type(X, Tr),
 2341            jpl_constructor_to_parameter_types(X, Tfps)
 2342        ;   length(Xs, J0),
 2343            nth1(J, Ms, M),     % generate members, continuing numbering
 2344            I is J0+J,
 2345            jpl_method_to_name(M, N),
 2346            jpl_method_to_modifiers(M, Mods),
 2347            jpl_method_to_return_type(M, Tr),
 2348            jpl_method_to_parameter_types(M, Tfps)
 2349        ),
 2350        length(Tfps, A), % arity
 2351        (   member(static, Mods)
 2352        ->  jGetStaticMethodID(C, N, method(Tfps,Tr), MID)
 2353        ;   jGetMethodID(C, N, method(Tfps,Tr), MID)
 2354        ),
 2355        jpl_assert(jpl_method_spec_cache(Tci,I,N,A,Mods,MID,Tr,Tfps)),
 2356        fail
 2357    ;   true
 2358    ).
 2359
 2360
 2361:- dynamic jpl_method_spec_cache/8. 2362
 2363
 2364:- dynamic jpl_method_spec_is_cached/1.
 jpl_method_to_modifiers(+Method:jref, -ModifierSet:ordset(modifier))
 2369jpl_method_to_modifiers(M, Ms) :-
 2370    jpl_classname_to_class('java.lang.reflect.Method', Cm),
 2371    jpl_method_to_modifiers_1(M, Cm, Ms).
 jpl_method_to_modifiers_1(+Method:jref, +ConstructorClass:jref, -ModifierSet:ordset(modifier))
 2376jpl_method_to_modifiers_1(XM, Cxm, Ms) :-
 2377    jGetMethodID(Cxm, getModifiers, method([],int), MID),
 2378    jCallIntMethod(XM, MID, [], [], I),
 2379    jpl_modifier_int_to_modifiers(I, Ms).
 jpl_method_to_name(+Method:jref, -Name:atom)
 2384jpl_method_to_name(M, N) :-
 2385    jpl_classname_to_class('java.lang.reflect.Method', CM),
 2386    jpl_member_to_name_1(M, CM, N).
 jpl_member_to_name_1(+Member:jref, +CM:jref, -Name:atom)
 2391jpl_member_to_name_1(M, CM, N) :-
 2392    jGetMethodID(CM, getName, method([],class([java,lang],['String'])), MID),
 2393    jCallObjectMethod(M, MID, [], [], N).
 jpl_method_to_parameter_types(+Method:jref, -Types:list(type))
 2398jpl_method_to_parameter_types(M, Tfps) :-
 2399    jpl_classname_to_class('java.lang.reflect.Method', Cm),
 2400    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]
 2407jpl_method_to_parameter_types_1(XM, Cxm, Tfps) :-
 2408    jGetMethodID(Cxm, getParameterTypes, method([],array(class([java,lang],['Class']))), MID),
 2409    jCallObjectMethod(XM, MID, [], [], Atp),
 2410    jpl_object_array_to_list(Atp, Ctps),
 2411    jpl_classes_to_types(Ctps, Tfps).
 jpl_method_to_return_type(+Method:jref, -Type:type)
 2416jpl_method_to_return_type(M, Tr) :-
 2417    jpl_classname_to_class('java.lang.reflect.Method', Cm),
 2418    jGetMethodID(Cm, getReturnType, method([],class([java,lang],['Class'])), MID),
 2419    jCallObjectMethod(M, MID, [], [], Cr),
 2420    jpl_class_to_type(Cr, Tr).
 2421
 2422
 2423jpl_modifier_bit(public,        0x001).
 2424jpl_modifier_bit(private,       0x002).
 2425jpl_modifier_bit(protected,     0x004).
 2426jpl_modifier_bit(static,        0x008).
 2427jpl_modifier_bit(final,         0x010).
 2428jpl_modifier_bit(synchronized,  0x020).
 2429jpl_modifier_bit(volatile,      0x040).
 2430jpl_modifier_bit(transient,     0x080).
 2431jpl_modifier_bit(native,        0x100).
 2432jpl_modifier_bit(interface,     0x200).
 2433jpl_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]
 2442jpl_modifier_int_to_modifiers(I, Ms) :-
 2443    setof(
 2444        M,                                  %  should use e.g. set_of_all/3
 2445        B^( jpl_modifier_bit(M, B),
 2446            (B /\ I) =\= 0
 2447        ),
 2448        Ms
 2449    ).
 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

 2463jpl_cache_type_of_ref(T, Ref) :-
 2464    (   jpl_assert_policy(jpl_iref_type_cache(_,_), no)
 2465    ->  true
 2466    ;   \+ ground(T)                            % shouldn't happen (implementation error)
 2467    ->  write('[jpl_cache_type_of_ref/2: arg 1 is not ground]'), nl,    % oughta throw an exception
 2468        fail
 2469    ;   Ref == @(null)                          % a null ref? (this is valid)
 2470    ->  true                                    % silently ignore it
 2471    ;   (   jpl_iref_type_cache(Ref, TC)        % we expect TC == T
 2472        ->  (   T == TC
 2473            ->  true
 2474            ; % write('[JPL: found obsolete tag-type lemma...]'), nl,   % or keep statistics? (why?)
 2475                retractall(jpl_iref_type_cache(Ref,_)),
 2476                jpl_assert(jpl_iref_type_cache(Ref,T))
 2477            )
 2478        ;   jpl_assert(jpl_iref_type_cache(Ref,T))
 2479        )
 2480    ).
 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)

 2491:- 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)
 2502jpl_class_to_ancestor_classes(C, Cas) :-
 2503    (   jpl_class_to_super_class(C, Ca)
 2504    ->  Cas = [Ca|Cas2],
 2505        jpl_class_to_ancestor_classes(Ca, Cas2)
 2506    ;   Cas = []
 2507    ).
 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)

 2521jpl_class_to_classname(C, CN) :-
 2522    jpl_call(C, getName, [], CN).
 jpl_class_to_raw_classname(+Class:jref, -ClassName:rawName)
The "raw classname" is the "name of the entity" as returned by Class.getName()

For example: "java.lang.String", "byte", "[Ljava.lang.Object;", "[[[[[[[I"

See also
- https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getName() https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Class.html#getName()
 2535jpl_class_to_raw_classname(Cobj, CN) :-
 2536    jpl_classname_to_class('java.lang.Class', CC),      % cached?
 2537    jGetMethodID(CC, getName, method([],class([java,lang],['String'])), MIDgetName),
 2538    jCallObjectMethod(Cobj, MIDgetName, [], [], S),
 2539    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

 2548jpl_class_to_raw_classname_chars(Cobj, CsCN) :-
 2549    jpl_class_to_raw_classname(Cobj, CN),
 2550    atom_codes(CN, CsCN).
 2551
 2552
 2553jpl_class_to_super_class(C, Cx) :-
 2554    jGetSuperclass(C, Cx),
 2555    Cx \== @(null),         % as returned when C is java.lang.Object, i.e. no superclass
 2556    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' (?!)

 2568jpl_class_to_type(Ref, Type) :-
 2569    (   jpl_class_tag_type_cache(Ref, Tx)
 2570    ->  true
 2571    ;   jpl_class_to_raw_classname_chars(Ref, Cs),   % uncached
 2572        jpl_classname_chars_to_type(Cs, Tr),
 2573        jpl_type_to_canonical_type(Tr, Tx),             % map e.g. class([],[byte]) -> byte
 2574        jpl_assert(jpl_class_tag_type_cache(Ref,Tx))
 2575    ->  true    % the elseif goal should be determinate, but just in case...
 2576    ),
 2577    Type = Tx.
 2578
 2579
 2580jpl_classes_to_types([], []).
 2581jpl_classes_to_types([C|Cs], [T|Ts]) :-
 2582    jpl_class_to_type(C, T),
 2583    jpl_classes_to_types(Cs, Ts).
 2584
 2585
 2586jpl_classname_chars_to_type(Cs, Type) :-
 2587    (   phrase(jpl_type_classname_1(Type), Cs)
 2588    ->  true
 2589    ).
 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.

 2600jpl_classname_to_class(N, C) :-
 2601    jpl_classname_to_type(N, T),    % cached
 2602    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?

 2615jpl_classname_to_type(CN, T) :-
 2616    (   jpl_classname_type_cache(CN, Tx)
 2617    ->  Tx = T
 2618    ;   atom_codes(CN, CsCN),
 2619        phrase(jpl_type_classname_1(T), CsCN)
 2620    ->  jpl_assert(jpl_classname_type_cache(CN,T)),
 2621        true
 2622    ).
 jpl_classname_type_cache(-Classname:className, -Type:type)
Classname is the atomic name of Type.

NB may denote a class which cannot be found.

 2631:- 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
 2646jpl_datum_to_type(D, T) :-
 2647    (   jpl_value_to_type(D, T)
 2648    ->  true
 2649    ;   jpl_ref_to_type(D, T)
 2650    ->  true
 2651    ;   nonvar(D),
 2652        D = {Term}
 2653    ->  (   cyclic_term(Term)
 2654        ->  throw_type_error(jpl_datum_to_type/2,acyclic,Term,er01)
 2655        ;   atom(Term)
 2656        ->  T = class([org,jpl7],['Atom'])
 2657        ;   integer(Term)
 2658        ->  T = class([org,jpl7],['Integer'])
 2659        ;   float(Term)
 2660        ->  T = class([org,jpl7],['Float'])
 2661        ;   var(Term)
 2662        ->  T = class([org,jpl7],['Variable'])
 2663        ;   T = class([org,jpl7],['Compound'])
 2664        )
 2665    ).
 2666
 2667
 2668jpl_datums_to_most_specific_common_ancestor_type([D], T) :-
 2669    jpl_datum_to_type(D, T).
 2670jpl_datums_to_most_specific_common_ancestor_type([D1,D2|Ds], T0) :-
 2671    jpl_datum_to_type(D1, T1),
 2672    jpl_type_to_ancestor_types(T1, Ts1),
 2673    jpl_datums_to_most_specific_common_ancestor_type_1([D2|Ds], [T1|Ts1], [T0|_]).
 2674
 2675
 2676jpl_datums_to_most_specific_common_ancestor_type_1([], Ts, Ts).
 2677jpl_datums_to_most_specific_common_ancestor_type_1([D|Ds], Ts1, Ts0) :-
 2678    jpl_datum_to_type(D, Tx),
 2679    jpl_lineage_types_type_to_common_lineage_types(Ts1, Tx, Ts2),
 2680    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).
 2691jpl_datums_to_types([], []).
 2692jpl_datums_to_types([D|Ds], [T|Ts]) :-
 2693    jpl_datum_to_type(D, T),
 2694    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.
 2701jpl_ground_is_type(X) :-
 2702    jpl_primitive_type(X),
 2703    !.
 2704jpl_ground_is_type(array(X)) :-
 2705    jpl_ground_is_type(X).
 2706jpl_ground_is_type(class(_,_)).
 2707jpl_ground_is_type(method(_,_)).
 2708
 2709
 2710:- dynamic jpl_iref_type_cache/2. 2711
 2712
 2713jpl_lineage_types_type_to_common_lineage_types(Ts, Tx, Ts0) :-
 2714    (   append(_, [Tx|Ts2], Ts)
 2715    ->  [Tx|Ts2] = Ts0
 2716    ;   jpl_type_to_super_type(Tx, Tx2)
 2717    ->  jpl_lineage_types_type_to_common_lineage_types(Ts, Tx2, Ts0)
 2718    ).
 2719
 2720
 2721jpl_non_var_is_object_type(class(_,_)).
 2722
 2723jpl_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.
 2731jpl_object_array_to_list(A, Vs) :-
 2732    jpl_array_to_length(A, N),
 2733    jpl_object_array_to_list_1(A, 0, N, Vs).
 jpl_object_array_to_list_1(+A, +I, +N, -Xs)
 2738jpl_object_array_to_list_1(A, I, N, Xs) :-
 2739    (   I == N
 2740    ->  Xs = []
 2741    ;   jGetObjectArrayElement(A, I, X),
 2742        Xs = [X|Xs2],
 2743        J is I+1,
 2744        jpl_object_array_to_list_1(A, J, N, Xs2)
 2745    ).
 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?

 2757jpl_object_to_class(Obj, C) :-
 2758    jpl_is_object(Obj),
 2759    jGetObjectClass(Obj, C),
 2760    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.

 2770jpl_object_to_type(Ref, Type) :-
 2771    jpl_is_object(Ref),
 2772    (   jpl_iref_type_cache(Ref, T)
 2773    ->  true                                % T is Tag's type
 2774    ;   jpl_object_to_class(Ref, Cobj),     % else get ref to class obj
 2775        jpl_class_to_type(Cobj, T),         % get type of class it denotes
 2776        jpl_assert(jpl_iref_type_cache(Ref,T))
 2777    ),
 2778    Type = T.
 2779
 2780
 2781jpl_object_type_to_super_type(T, Tx) :-
 2782    (   (   T = class(_,_)
 2783        ;   T = array(_)
 2784        )
 2785    ->  jpl_type_to_class(T, C),
 2786        jpl_class_to_super_class(C, Cx),
 2787        Cx \== @(null),
 2788        jpl_class_to_type(Cx, Tx)
 2789    ).
 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)

 2800jpl_primitive_buffer_to_array(T, Xc, Bp, I, Size, [Vc|Vcs]) :-
 2801    jni_fetch_buffer_value(Bp, I, Vc, Xc),
 2802    Ix is I+1,
 2803    (   Ix < Size
 2804    ->  jpl_primitive_buffer_to_array(T, Xc, Bp, Ix, Size, Vcs)
 2805    ;   Vcs = []
 2806    ).
 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].
 2818jpl_primitive_type(boolean).
 2819jpl_primitive_type(char).
 2820jpl_primitive_type(byte).
 2821jpl_primitive_type(short).
 2822jpl_primitive_type(int).
 2823jpl_primitive_type(long).
 2824jpl_primitive_type(float).
 2825jpl_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).
 2834jpl_primitive_type_default_value(boolean, @(false)).
 2835jpl_primitive_type_default_value(char,    0).
 2836jpl_primitive_type_default_value(byte,    0).
 2837jpl_primitive_type_default_value(short,   0).
 2838jpl_primitive_type_default_value(int,     0).
 2839jpl_primitive_type_default_value(long,    0).
 2840jpl_primitive_type_default_value(float,   0.0).
 2841jpl_primitive_type_default_value(double,  0.0).
 2842
 2843
 2844jpl_primitive_type_super_type(T, Tx) :-
 2845    (   jpl_type_fits_type_direct_prim(T, Tx)
 2846    ;   jpl_type_fits_type_direct_xtra(T, Tx)
 2847    ).
 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)

 2860jpl_primitive_type_term_to_value(Type, Term, Val) :-
 2861    (   jpl_primitive_type_term_to_value_1(Type, Term, Val)
 2862    ->  true
 2863    ).
 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.

 2872jpl_primitive_type_term_to_value_1(boolean, @(false), @(false)).
 2873jpl_primitive_type_term_to_value_1(boolean, @(true), @(true)).
 2874jpl_primitive_type_term_to_value_1(char, I, I) :-
 2875    integer(I),
 2876    I >= 0,
 2877    I =< 65535.         %  (2**16)-1.
 2878jpl_primitive_type_term_to_value_1(byte, I, I) :-
 2879    integer(I),
 2880    I >= 128,           % -(2**7)
 2881    I =< 127.           %  (2**7)-1
 2882jpl_primitive_type_term_to_value_1(short, I, I) :-
 2883    integer(I),
 2884    I >= -32768,        % -(2**15)
 2885    I =<  32767.        %  (2**15)-1
 2886jpl_primitive_type_term_to_value_1(int, I, I) :-
 2887    integer(I),
 2888    I >= -2147483648,   % -(2**31)
 2889    I =<  2147483647.   %  (2**31)-1
 2890jpl_primitive_type_term_to_value_1(long, I, I) :-
 2891    integer(I),
 2892    I >= -9223372036854775808,  % -(2**63)
 2893    I =<  9223372036854775807.  %  (2**63)-1
 2894jpl_primitive_type_term_to_value_1(float, V, F) :-
 2895    (   integer(V)
 2896    ->  F is float(V)
 2897    ;   float(V)
 2898    ->  F = V
 2899    ).
 2900jpl_primitive_type_term_to_value_1(double, V, F) :-
 2901    (   integer(V)
 2902    ->  F is float(V)
 2903    ;   float(V)
 2904    ->  F = V
 2905    ).
 2906
 2907
 2908jpl_primitive_type_to_ancestor_types(T, Ts) :-
 2909    (   jpl_primitive_type_super_type(T, Ta)
 2910    ->  Ts = [Ta|Tas],
 2911        jpl_primitive_type_to_ancestor_types(Ta, Tas)
 2912    ;   Ts = []
 2913    ).
 2914
 2915
 2916jpl_primitive_type_to_super_type(T, Tx) :-
 2917    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.

 2926jpl_ref_to_type(Ref, T) :-
 2927    (   Ref == @(null)
 2928    ->  T = null
 2929    ;   Ref == @(void)
 2930    ->  T = void
 2931    ;   jpl_object_to_type(Ref, T)
 2932    ).
 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

 2942jpl_tag_to_type(Tag, Type) :-
 2943    jni_tag_to_iref(Tag, Iref),
 2944    (   jpl_iref_type_cache(Iref, T)
 2945    ->  true                                % T is Tag's type
 2946    ;   jpl_object_to_class(@(Tag), Cobj), % else get ref to class obj
 2947        jpl_class_to_type(Cobj, T),         % get type of class it denotes
 2948        jpl_assert(jpl_iref_type_cache(Iref,T))
 2949    ),
 2950    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.

 2959jpl_type_fits_type(Tx, Ty) :-
 2960    (   jpl_type_fits_type_1(Tx, Ty)
 2961    ->  true
 2962    ).
 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
 2969jpl_type_fits_type_1(T, T).
 2970jpl_type_fits_type_1(class(Ps1,Cs1), class(Ps2,Cs2)) :-
 2971    jpl_type_to_class(class(Ps1,Cs1), C1),
 2972    jpl_type_to_class(class(Ps2,Cs2), C2),
 2973    jIsAssignableFrom(C1, C2).
 2974jpl_type_fits_type_1(array(T1), class(Ps2,Cs2)) :-
 2975    jpl_type_to_class(array(T1), C1),
 2976    jpl_type_to_class(class(Ps2,Cs2), C2),
 2977    jIsAssignableFrom(C1, C2).
 2978jpl_type_fits_type_1(array(T1), array(T2)) :-
 2979    jpl_type_to_class(array(T1), C1),
 2980    jpl_type_to_class(array(T2), C2),
 2981    jIsAssignableFrom(C1, C2).
 2982jpl_type_fits_type_1(null, class(_,_)).
 2983jpl_type_fits_type_1(null, array(_)).
 2984jpl_type_fits_type_1(T1, T2) :-
 2985    jpl_type_fits_type_xprim(T1, T2).
 2986
 2987
 2988jpl_type_fits_type_direct_prim(float, double).
 2989jpl_type_fits_type_direct_prim(long,  float).
 2990jpl_type_fits_type_direct_prim(int,   long).
 2991jpl_type_fits_type_direct_prim(char,  int).
 2992jpl_type_fits_type_direct_prim(short, int).
 2993jpl_type_fits_type_direct_prim(byte,  short).
 2994
 2995
 2996jpl_type_fits_type_direct_xprim(Tp, Tq) :-
 2997    jpl_type_fits_type_direct_prim(Tp, Tq).
 2998jpl_type_fits_type_direct_xprim(Tp, Tq) :-
 2999    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
 3007jpl_type_fits_type_direct_xtra(char_int,   int).    % char_int is a direct subtype of int
 3008jpl_type_fits_type_direct_xtra(char_int,   char).   % etc.
 3009jpl_type_fits_type_direct_xtra(char_short, short).
 3010jpl_type_fits_type_direct_xtra(char_short, char).
 3011jpl_type_fits_type_direct_xtra(char_byte,  byte).
 3012jpl_type_fits_type_direct_xtra(char_byte,  char).
 3013jpl_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
 3020jpl_type_fits_type_xprim(Tp, T) :-
 3021    jpl_type_fits_type_direct_xprim(Tp, Tq),
 3022    (   Tq = T
 3023    ;   jpl_type_fits_type_xprim(Tq, T)
 3024    ).
 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.
 3032jpl_type_to_ancestor_types(T, Tas) :-
 3033    (   (   T = class(_,_)
 3034        ;   T = array(_)
 3035        )
 3036    ->  jpl_type_to_class(T, C),
 3037        jpl_class_to_ancestor_classes(C, Cas),
 3038        jpl_classes_to_types(Cas, Tas)
 3039    ;   jpl_primitive_type_to_ancestor_types(T, Tas)
 3040    ->  true
 3041    ).
 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.
 3056jpl_type_to_canonical_type(array(T), array(Tc)) :-
 3057    !,
 3058    jpl_type_to_canonical_type(T, Tc).
 3059jpl_type_to_canonical_type(class([],[void]), void) :-
 3060    !.
 3061jpl_type_to_canonical_type(class([],[N]), N) :-
 3062    jpl_primitive_type(N),
 3063    !.
 3064jpl_type_to_canonical_type(class(Ps,Cs), class(Ps,Cs)) :-
 3065    !.
 3066jpl_type_to_canonical_type(void, void) :-
 3067    !.
 3068jpl_type_to_canonical_type(P, P) :-
 3069    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.

 3078jpl_type_to_class(T, RefA) :-
 3079    (   ground(T)
 3080	->  (   jpl_class_tag_type_cache(RefB, T)
 3081	    ->  true
 3082	    ;   (   jpl_type_to_findclassname(T, FCN)   % peculiar syntax for FindClass()
 3083	        ->  jFindClass(FCN, RefB),       % which caches type of RefB
 3084	            jpl_cache_type_of_ref(class([java,lang],['Class']), RefB)    % 9/Nov/2004 bugfix (?)
 3085	        ),
 3086	        jpl_assert(jpl_class_tag_type_cache(RefB,T))
 3087	    ),
 3088	    RefA = RefB
 3089    ;   throw_instantiation_error(jpl_type_to_class/2,es01)
 3090    ).
 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
 3113jpl_type_to_nicename(T, NN) :-
 3114    (   jpl_primitive_type(T)
 3115    ->  NN = T
 3116    ;   (   phrase(jpl_type_classname_1(T), Cs)
 3117        ->  atom_codes(CNx, Cs),                                % green commit to first solution
 3118            NN = CNx
 3119        )
 3120    ).
 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
 3132jpl_type_to_classname(T, CN) :-
 3133    (   phrase(jpl_type_classname_1(T), Cs)
 3134    ->  atom_codes(CNx, Cs),                                % green commit to first solution
 3135        CN = CNx
 3136    ).
 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?)

 3153jpl_type_to_descriptor(T, D) :-
 3154    (   phrase(jpl_type_descriptor_1(T), Cs)
 3155    ->  atom_codes(Dx, Cs),
 3156        D = Dx
 3157    ).
 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'.
 3171jpl_type_to_findclassname(T, FCN) :-
 3172    (   phrase(jpl_type_findclassname(T), Cs)
 3173    ->  atom_codes(FCNx, Cs),
 3174        FCN = FCNx
 3175    ).
 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.

 3186jpl_type_to_super_type(T, Tx) :-
 3187    (   jpl_object_type_to_super_type(T, Tx)
 3188    ->  true
 3189    ;   jpl_primitive_type_to_super_type(T, Tx)
 3190    ->  true
 3191    ).
 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

 3210jpl_type_to_preferred_concrete_type(T, Tc) :-
 3211    (   jpl_type_to_preferred_concrete_type_1(T, TcX)
 3212    ->  Tc = TcX
 3213    ).
 3214
 3215
 3216jpl_type_to_preferred_concrete_type_1(char_int, int).
 3217jpl_type_to_preferred_concrete_type_1(char_short, short).
 3218jpl_type_to_preferred_concrete_type_1(char_byte, byte).
 3219jpl_type_to_preferred_concrete_type_1(array(T), array(Tc)) :-
 3220    jpl_type_to_preferred_concrete_type_1(T, Tc).
 3221jpl_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.

 3230jpl_types_fit_type([], _).
 3231jpl_types_fit_type([T1|T1s], T2) :-
 3232    jpl_type_fits_type(T1, T2),
 3233    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.
 3240jpl_types_fit_types([], []).
 3241jpl_types_fit_types([T1|T1s], [T2|T2s]) :-
 3242    jpl_type_fits_type(T1, T2),
 3243    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.

 3254jpl_value_to_type(V, T) :-
 3255    ground(V),                          % critically assumed by jpl_value_to_type_1/2
 3256    (   jpl_value_to_type_1(V, Tv)      % 2nd arg must be unbound
 3257    ->  T = Tv
 3258    ).
 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.

 3275jpl_value_to_type_1(@(false), boolean) :- !.
 3276jpl_value_to_type_1(@(true), boolean) :- !.
 3277jpl_value_to_type_1(A, class([java,lang],['String'])) :-   % yes it's a "value"
 3278    atom(A),
 3279    !.
 3280jpl_value_to_type_1(I, T) :-
 3281    integer(I),
 3282    !,
 3283    (   I >= 0
 3284    ->  (   I  < 128                 ->  T = char_byte
 3285        ;   I  < 32768               ->  T = char_short
 3286        ;   I  < 65536               ->  T = char_int
 3287        ;   I  < 2147483648          ->  T = int
 3288        ;   I =< 9223372036854775807 ->  T = long
 3289        ;   T = overlong
 3290        )
 3291    ;   I >= -128                 ->  T = byte
 3292    ;   I >= -32768               ->  T = short
 3293    ;   I >= -2147483648          ->  T = int
 3294    ;   I >= -9223372036854775808 ->  T = long
 3295    ;   T = overlong
 3296    ).
 3297jpl_value_to_type_1(F, float) :-
 3298    float(F).
 jpl_is_class(@Term)
True if Term is a JPL reference to an instance of java.lang.Class.
 3305jpl_is_class(X) :-
 3306    jpl_is_object(X),
 3307    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'.
 3314jpl_is_false(X) :-
 3315    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.

 3328jpl_is_fieldID(jfieldID(X)) :-
 3329    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.

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

 3360jpl_is_object(X) :-
 3361	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.
 3368jpl_is_object_type(T) :-
 3369    \+ var(T),
 3370    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.
 3379jpl_is_ref(Term) :-
 3380    (	jpl_is_object(Term)
 3381    ->	true
 3382    ;	jpl_is_null(Term)
 3383    ->	true
 3384    ).
 jpl_is_true(@Term)
True if Term is @(true), the JPL representation of the Java boolean value 'true'.
 3392jpl_is_true(X) :-
 3393    X == @(true).
 jpl_is_type(@Term)
True if Term is a well-formed JPL type structure.
 3399jpl_is_type(X) :-
 3400    ground(X),
 3401    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.

 3412jpl_is_void(X) :-
 3413    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
 3422jpl_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
 3430jpl_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
 3439jpl_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
 3449jpl_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)
    ).
 3466jpl_array_to_length(A, N) :-
 3467    (   jpl_ref_to_type(A, array(_))    % can this be done cheaper e.g. in foreign code?
 3468    ->  jGetArrayLength(A, N)           % *must* be array, else undefined (crash?)
 3469    ).
 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 = []
    ).
 3491jpl_array_to_list(A, Es) :-
 3492    jpl_array_to_length(A, Len),
 3493    (   Len > 0
 3494    ->  LoBound is 0,
 3495        HiBound is Len-1,
 3496        jpl_get(A, LoBound-HiBound, Es)
 3497    ;   Es = []
 3498    ).
 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

 3513jpl_datums_to_array(Ds, A) :-
 3514    ground(Ds),
 3515    jpl_datums_to_most_specific_common_ancestor_type(Ds, T),    % T may be pseudo e.g. char_byte
 3516    jpl_type_to_preferred_concrete_type(T, Tc),    % bugfix added 16/Apr/2005
 3517    jpl_new(array(Tc), Ds, A).
 jpl_enumeration_element(+Enumeration:jref, -Element:datum)
Generates each Element from Enumeration.
 3528jpl_enumeration_element(En, E) :-
 3529    (   jpl_call(En, hasMoreElements, [], @(true))
 3530    ->  jpl_call(En, nextElement, [], Ex),
 3531        (   E = Ex
 3532        ;   jpl_enumeration_element(En, E)
 3533        )
 3534    ).
 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 = []
    ).
 3555jpl_enumeration_to_list(Enumeration, Es) :-
 3556    (   jpl_call(Enumeration, hasMoreElements, [], @(true))
 3557    ->  jpl_call(Enumeration, nextElement, [], E),
 3558        Es = [E|Es1],
 3559        jpl_enumeration_to_list(Enumeration, Es1)
 3560    ;   Es = []
 3561    ).
 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.

 3573jpl_hashtable_pair(HT, K-V) :-
 3574    jpl_call(HT, keys, [], Ek),
 3575    jpl_enumeration_to_list(Ek, Ks),
 3576    member(K, Ks),
 3577    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)
        )
    ).
 3597jpl_iterator_element(I, E) :-
 3598    (   jpl_call(I, hasNext, [], @(true))
 3599    ->  (   jpl_call(I, next, [], E)
 3600        ;   jpl_iterator_element(I, E)
 3601        )
 3602    ).
 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.

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

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

 4050check_java_environment :-
 4051    current_prolog_flag(apple, true),
 4052    !,
 4053    print_message(error, jpl(run(jpl_config_dylib))).
 4054check_java_environment :-
 4055    check_lib(jvm).
 4056
 4057check_lib(Name) :-
 4058    check_shared_object(Name, File, EnvVar, Absolute),
 4059    (   Absolute == (-)
 4060    ->  env_var_separators(A, Z),
 4061        format(string(Msg), 'Please add directory holding ~w to ~w~w~w',
 4062               [ File, A, EnvVar, Z ]),
 4063        throw_existence_error(check_lib/1,library,Name,Msg)
 4064    ;   true
 4065    ).
 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.
 4074check_shared_object(Name, File, EnvVar, Absolute) :-
 4075    libfile(Name, File),
 4076    library_search_path(Path, EnvVar),
 4077    (   member(Dir, Path),
 4078        atomic_list_concat([Dir, File], /, Absolute),
 4079        exists_file(Absolute)
 4080    ->  true
 4081    ;   Absolute = (-)
 4082    ).
 4083
 4084libfile(Base, File) :-
 4085    current_prolog_flag(unix, true),
 4086    !,
 4087    atom_concat(lib, Base, F0),
 4088    current_prolog_flag(shared_object_extension, Ext),
 4089    file_name_extension(F0, Ext, File).
 4090libfile(Base, File) :-
 4091    current_prolog_flag(windows, true),
 4092    !,
 4093    current_prolog_flag(shared_object_extension, Ext),
 4094    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.
 4102library_search_path(Path, EnvVar) :-
 4103    current_prolog_flag(shared_object_search_path, EnvVar),
 4104    search_path_separator(Sep),
 4105    (   getenv(EnvVar, Env),
 4106        atomic_list_concat(Path, Sep, Env)
 4107    ->  true
 4108    ;   Path = []
 4109    ).
 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?
 4123add_jpl_to_classpath :-
 4124    classpath(Jar),
 4125    file_base_name(Jar, 'jpl.jar'),
 4126    !.
 4127add_jpl_to_classpath :-
 4128    classpath(Dir),
 4129    (   sub_atom(Dir, _, _, 0, /)
 4130    ->  atom_concat(Dir, 'jpl.jar', File)
 4131    ;   atom_concat(Dir, '/jpl.jar', File)
 4132    ),
 4133    access_file(File, read),
 4134    !.
 4135add_jpl_to_classpath :-
 4136    absolute_file_name(jar('jpl.jar'), JplJAR,
 4137                       [ access(read)
 4138                       ]),
 4139    !,
 4140    (   getenv('CLASSPATH', Old)
 4141    ->  search_path_separator(Separator),
 4142        atomic_list_concat([JplJAR, Old], Separator, New)
 4143    ;   New = JplJAR
 4144    ),
 4145    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.

In Windows we should not use foreign(jpl) as this eventually calls LoadLibrary() with an absolute path, disabling the Windows DLL search process for the dependent jvm.dll and possibly other Java dll dependencies.

 4159libjpl(File) :-
 4160    (   current_prolog_flag(unix, true)
 4161    ->  File = foreign(libjpl)
 4162    ;   File = foreign(jpl)                                    % Windows
 4163    ).
 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.
 4172add_jpl_to_ldpath(JPL) :-
 4173    absolute_file_name(JPL, File,
 4174               [ file_type(executable),
 4175                 access(read),
 4176                 file_errors(fail)
 4177               ]),
 4178    !,
 4179    file_directory_name(File, Dir),
 4180    prolog_to_os_filename(Dir, OsDir),
 4181    extend_java_library_path(OsDir),
 4182    current_prolog_flag(shared_object_search_path, PathVar),
 4183    add_search_path(PathVar, OsDir).
 4184add_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.
 4193:- if(current_prolog_flag(windows,true)). 4194add_java_to_ldpath :-
 4195    current_prolog_flag(windows, true),
 4196    !,
 4197    phrase(java_dirs, Extra),
 4198    (   Extra \== []
 4199    ->  print_message(informational, extend_ld_path(Extra)),
 4200        maplist(extend_dll_search_path, Extra)
 4201    ;   true
 4202    ).
 4203:- endif. 4204add_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.
 4213:- if(current_prolog_flag(windows,true)). 4214extend_dll_search_path(Dir) :-
 4215    win_add_dll_directory(Dir),
 4216    (   current_prolog_flag(wine_version, _)
 4217    ->  prolog_to_os_filename(Dir, OSDir),
 4218        (   getenv('PATH', Path0)
 4219        ->  atomic_list_concat([Path0, OSDir], ';', Path),
 4220            setenv('PATH', Path)
 4221        ;   setenv('PATH', OSDir)
 4222        )
 4223    ;   true
 4224    ).
 4225:- endif.
 extend_java_library_path(+OsDir)
Add Dir (in OS notation) to the Java -Djava.library.path init options.
 4232extend_java_library_path(OsDir) :-
 4233    jpl_get_default_jvm_opts(Opts0),
 4234    (   select(PathOpt0, Opts0, Rest),
 4235        sub_atom(PathOpt0, 0, _, _, '-Djava.library.path=')
 4236    ->  search_path_separator(Separator),
 4237        atomic_list_concat([PathOpt0, Separator, OsDir], PathOpt),
 4238        NewOpts = [PathOpt|Rest]
 4239    ;   atom_concat('-Djava.library.path=', OsDir, PathOpt),
 4240        NewOpts = [PathOpt|Opts0]
 4241    ),
 4242    debug(jpl(path), 'Setting Java options to ~p', [NewOpts]),
 4243    jpl_set_default_jvm_opts(NewOpts).
 java_dirs// is det
DCG that produces existing candidate directories holding Java related DLLs
 4250java_dirs -->
 4251    % JDK directories
 4252    java_dir(jvm, '/jre/bin/client'),
 4253    java_dir(jvm, '/jre/bin/server'),
 4254    java_dir(java, '/jre/bin'),
 4255    % JRE directories
 4256    java_dir(jvm, '/bin/client'),
 4257    java_dir(jvm, '/bin/server'),
 4258    java_dir(java, '/bin').
 4259
 4260java_dir(DLL, _SubPath) -->
 4261    { check_shared_object(DLL, _, _Var, Abs),
 4262      Abs \== (-)
 4263    },
 4264    !.
 4265java_dir(_DLL, SubPath) -->
 4266    { java_home(JavaHome),
 4267      atom_concat(JavaHome, SubPath, SubDir),
 4268      exists_directory(SubDir)
 4269    },
 4270    !,
 4271    [SubDir].
 4272java_dir(_, _) --> [].
 java_home(-Home) is semidet
Find the home location of Java.
Arguments:
Home- JAVA home in OS notation
 4281java_home_win_key(
 4282    jdk,
 4283    'HKEY_LOCAL_MACHINE/Software/JavaSoft/JDK'). % new style
 4284java_home_win_key(
 4285    jdk,
 4286    'HKEY_LOCAL_MACHINE/Software/JavaSoft/Java Development Kit').
 4287java_home_win_key(
 4288    jre,
 4289    'HKEY_LOCAL_MACHINE/Software/JavaSoft/JRE').
 4290java_home_win_key(
 4291    jre,
 4292    'HKEY_LOCAL_MACHINE/Software/JavaSoft/Java Runtime Environment').
 4293
 4294java_home(Home) :-
 4295    getenv('JAVA_HOME', Home),
 4296    exists_directory(Home),
 4297    !.
 4298:- if(current_prolog_flag(windows, true)). 4299java_home(Home) :-
 4300    java_home_win_key(_, Key0),    % TBD: user can't choose jre or jdk
 4301    catch(win_registry_get_value(Key0, 'CurrentVersion', Version), _, fail),
 4302    atomic_list_concat([Key0, Version], /, Key),
 4303    win_registry_get_value(Key, 'JavaHome', WinHome),
 4304    prolog_to_os_filename(Home, WinHome),
 4305    exists_directory(Home),
 4306    !.
 4307:- else. 4308java_home(Home) :-
 4309    member(Home, [ '/usr/lib/java',
 4310                   '/usr/local/lib/java'
 4311                 ]),
 4312    exists_directory(Home),
 4313    !.
 4314:- endif. 4315
 4316:- dynamic
 4317    jvm_ready/0. 4318:- volatile
 4319    jvm_ready/0. 4320
 4321setup_jvm :-
 4322    jvm_ready,
 4323    !.
 4324setup_jvm :-
 4325    add_jpl_to_classpath,
 4326    add_java_to_ldpath,
 4327    libjpl(JPL),
 4328    catch(load_foreign_library(JPL), E, report_java_setup_problem(E)),
 4329    add_jpl_to_ldpath(JPL),
 4330    assert(jvm_ready).
 4331
 4332report_java_setup_problem(E) :-
 4333    print_message(error, E),
 4334    check_java_environment.
 4335
 4336         /*******************************
 4337         *          MESSAGES            *
 4338         *******************************/
 4339
 4340:- multifile
 4341    prolog:message//1. 4342
 4343prolog:message(extend_ld_path(Dirs)) -->
 4344    [ 'Extended DLL search path with'-[] ],
 4345    dir_per_line(Dirs).
 4346prolog:message(jpl(run(Command))) -->
 4347    [ 'Could not find libjpl.dylib dependencies.'-[],
 4348      'Please run `?- ~p.` to correct this'-[Command]
 4349    ].
 4350
 4351dir_per_line([]) --> [].
 4352dir_per_line([H|T]) -->
 4353    [ nl, '  ~q'-[H] ],
 4354    dir_per_line(T).
 4355
 4356         /*******************************
 4357         *      EXCEPTION HANDLING      *
 4358         *******************************/
 4359
 4360% Cleartext messages that are carried by exceptions.
 4361% They are looked up by a meaningless atom (i.e. an "error code")
 4362% No effort has been made to collapse identicial messages ... yet.
 4363
 4364exception_msg(ea01,'1st arg must be bound to a classname, descriptor or object type').
 4365exception_msg(ea02,'if 1st arg is an atom, it must be a classname or descriptor').
 4366exception_msg(ea03,'1st arg must be a classname, descriptor or object type').
 4367exception_msg(ea04,'result is not a org.jpl7.Term instance as required').
 4368
 4369% ---
 4370
 4371exception_msg(eb01,'2nd arg must be a proper list of valid parameters for a constructor').
 4372exception_msg(eb03,'cannot create instance of an interface').
 4373exception_msg(eb04,'no constructor found with the corresponding quantity of parameters').
 4374exception_msg(eb05,'one or more of the actual parameters is not a valid representation of any Java value or object').
 4375exception_msg(eb06,'the actual parameters are not assignable to the formal parameter types of the only constructor which takes this qty of parameters').
 4376exception_msg(eb07,'the actual parameters are not assignable to the formal parameter types of any of the constructors which take this qty of parameters').
 4377exception_msg(eb08,'more than one most-specific matching constructor (shouldn''t happen)').
 4378exception_msg(eb09,'cannot create instance of an abstract class').
 4379
 4380% ---
 4381
 4382exception_msg(ec01,'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').
 4383exception_msg(ec02,'when constructing a new array, if the 2nd arg is an integer (denoting the required array length) then it must be non-negative').
 4384
 4385% ---
 4386
 4387exception_msg(ed01,'cannot construct an instance of a primitive type').
 4388exception_msg(ed02,'when constructing a new instance of a primitive type, 2nd arg must be bound (to a representation of a suitable value)').
 4389exception_msg(ed03,'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)').
 4390
 4391% ---
 4392
 4393exception_msg(ee01,'1st arg must denote a known or plausible type').
 4394
 4395% ---
 4396
 4397exception_msg(ef01,'1st arg must be bound to an object, classname, descriptor or type').
 4398exception_msg(ef02,'the named class cannot be found').
 4399exception_msg(ef03,'1st arg must be an object, classname, descriptor or type').
 4400exception_msg(ef04,'cannot call a static method of an array type, as none exists').
 4401exception_msg(ef05,'2nd arg must be an atom naming a public method of the class or object').
 4402exception_msg(ef06,'not all actual parameters are convertible to Java values or references').
 4403exception_msg(ef07,'3rd arg must be a proper list of actual parameters for the named method').
 4404exception_msg(ef08,'result is not a org.jpl7.Term instance as required').
 4405
 4406% ---
 4407
 4408exception_msg(eg01,'the class or object has no public methods with the given name and quantity of parameters').
 4409exception_msg(eg02,'the actual parameters are not assignable to the formal parameters of any of the named methods').
 4410exception_msg(eg03,'more than one most-specific method is found for the actual parameters (this should not happen)').
 4411
 4412% ---
 4413
 4414exception_msg(eh01,'the class has no public static methods with the given name and quantity of parameters').
 4415exception_msg(eh02,'the actual parameters are not assignable to the formal parameters of any of the named methods').
 4416exception_msg(eh03,'more than one most-specific method is found for the actual parameters (this should not happen)').
 4417
 4418% ---
 4419
 4420exception_msg(ei01,'1st arg must be bound to an object, classname, descriptor or type').
 4421exception_msg(ei02,'the named class cannot be found').
 4422exception_msg(ei03,'1st arg must be an object, classname, descriptor or type').
 4423exception_msg(ei04,'result is not a org.jpl7.Term instance as required').
 4424
 4425% ---
 4426
 4427exception_msg(ej01,'2nd arg must be bound to an atom naming a public field of the class').
 4428exception_msg(ej02,'2nd arg must be an atom naming a public field of the class').
 4429exception_msg(ej03,'the class or object has no public static field with the given name').
 4430exception_msg(ej04,'more than one field is found with the given name').
 4431
 4432% ---
 4433
 4434exception_msg(ek01,'2nd arg must be bound to an atom naming a public field of the class or object').
 4435exception_msg(ek02,'2nd arg must be an atom naming a public field of the class or object').
 4436exception_msg(ek03,'the class or object has no public field with the given name').
 4437exception_msg(ek04,'more than one field is found with the given name').
 4438
 4439% ---
 4440
 4441exception_msg(el01,'when 1st arg is an array, 2nd arg must be bound to an index, an index range, or ''length''').
 4442exception_msg(el02,'when 1st arg is an array, integral 2nd arg must be non-negative').
 4443exception_msg(el03,'when 1st arg is an array, integral 2nd arg must not exceed upper bound of array').
 4444exception_msg(el04,'lower bound of array index range must not exceed upper bound of array').
 4445exception_msg(el05,'upper bound of array index range must not exceed upper bound of array').
 4446exception_msg(el06,'array index range must be a non-decreasing pair of non-negative integers').
 4447exception_msg(el07,'the array has no public field with the given name').
 4448exception_msg(el08,'when 1st arg is an array, 2nd arg must be an index, an index range, or ''length''').
 4449
 4450% ---
 4451
 4452exception_msg(em01,'1st arg must be an object, classname, descriptor or type').
 4453exception_msg(em02,'the named class cannot be found').
 4454exception_msg(em03,'the class cannot be found').
 4455exception_msg(em04,'1st arg must be an object, classname, descriptor or type').
 4456
 4457% ---
 4458
 4459exception_msg(en01,'2nd arg must be bound to the name of a public, non-final field').
 4460exception_msg(en02,'2nd arg must be the name of a public, non-final field').
 4461exception_msg(en03,'no public fields of the object have this name').
 4462exception_msg(en04,'cannot assign a value to a final field (actually you could but I''ve decided not to let you)').
 4463exception_msg(en05,'the value is not assignable to the named field of the class').
 4464exception_msg(en06,'3rd arg does not represent any Java value or object').
 4465exception_msg(en07,'more than one public field of the object has this name (this should not happen)').
 4466
 4467% ---
 4468
 4469exception_msg(eo01,'when 1st arg is an array, 3rd arg must be bound to a suitable element value or list of values').
 4470exception_msg(eo02,'when 1st arg is an array, 2nd arg must be bound to an index or index range').
 4471exception_msg(eo03,'when 1st arg is an array, an integral 2nd arg must be a non-negative index').
 4472exception_msg(eo04,'no values for array element assignment: needs one').
 4473exception_msg(eo05,'too many values for array element assignment: needs one').
 4474exception_msg(eo06,'too few values for array range assignment').
 4475exception_msg(eo07,'too many values for array range assignment').
 4476exception_msg(eo08,'array index range must be a non-decreasing pair of non-negative integers').
 4477exception_msg(eo09,'cannot assign a value to a final field').
 4478exception_msg(eo10,'array has no field with that name').
 4479exception_msg(eo11,'when 1st arg is an array object, 2nd arg must be a non-negative index or index range').
 4480
 4481% ---
 4482
 4483exception_msg(ep01,'when 1st arg denotes a class, 2nd arg must be bound to the name of a public, static, non-final field').
 4484exception_msg(ep02,'when 1st arg denotes a class, 2nd arg must be the name of a public, static, non-final field').
 4485exception_msg(ep03,'class has no public static fields of this name').
 4486exception_msg(ep04,'cannot assign a value to a final field').
 4487exception_msg(ep05,'the value is not assignable to the named field of the class').
 4488exception_msg(ep06,'3rd arg does not represent any Java value or object').
 4489exception_msg(ep07,'more than one public static field of the class has this name (this should not happen)(?)').
 4490
 4491% ---
 4492
 4493exception_msg(eq01,'not all values are assignable to the array element type').
 4494exception_msg(eq02,'not all values are convertible to Java values or references').
 4495exception_msg(eq03,'array element type is unknown: neither a class, nor an array type, nor a primitive type').
 4496
 4497% ---
 4498
 4499exception_msg(er01,'must be acyclic').
 4500
 4501% ---
 4502
 4503exception_msg(es01,'1st arg must be bound to a JPL type').
 4504
 4505% The predicates that throw.
 4506% Pred+    is generally the predicate descriptor of the predicate raising the exception.
 4507% MsgCode+ is the atom indicating which cleartext message to insert into the exception term.
 4508
 4509from_msg_code(MsgCode,MsgText) :-
 4510   (exception_msg(MsgCode,MsgText) -> true ; (MsgText = MsgCode)).
 4511
 4512throw_instantiation_error(Pred,MsgCode) :-
 4513   from_msg_code(MsgCode,MsgText),
 4514   Formal  = instantiation_error,
 4515   Context = context(Pred,MsgText),
 4516   throw(error(Formal,Context)).
 4517
 4518throw_domain_error(Pred,ValidDomain,Culprit,MsgCode) :-
 4519   from_msg_code(MsgCode,MsgText),
 4520   Formal  = domain_error(ValidDomain,Culprit),
 4521   Context = context(Pred,MsgText),
 4522   throw(error(Formal,Context)).
 4523
 4524throw_type_error(Pred,ValidType,Culprit,MsgCode) :-
 4525   from_msg_code(MsgCode,MsgText),
 4526   Formal  = type_error(ValidType,Culprit),
 4527   Context = context(Pred,MsgText),
 4528   throw(error(Formal,Context)).
 4529
 4530throw_existence_error(Pred,ObjectType,Culprit,MsgCode) :-
 4531   from_msg_code(MsgCode,MsgText),
 4532   Formal = existence_error(ObjectType,Culprit),
 4533   Context = context(Pred,MsgText),
 4534   throw(error(Formal,Context)).
 4535
 4536throw_permission_error(Pred,Operation,PermissionType,Culprit,MsgCode) :-
 4537   from_msg_code(MsgCode,MsgText),
 4538   Formal  = permission_error(Operation,PermissionType,Culprit),
 4539   Context = context(Pred,MsgText),
 4540   throw(error(Formal,Context)).
 4541
 4542         /*******************************
 4543         *      Initialize JVM          *
 4544         *******************************/
 4545
 4546:- initialization(setup_jvm, now).        % must be ready before export