public class NativeInvoker
extends java.lang.Object
LibraryDaemon
and LibraryManager
).
All the functionality of this class (actually, of the entire package) is exposed via two
methods, invoke(java.lang.String, java.lang.String, java.lang.String, java.lang.Class<?>[], java.lang.String, java.lang.Object...)
and release(java.lang.String)
.
Modifier and Type | Class and Description |
---|---|
private static class |
NativeInvoker.WorkArea
Container for context-local data.
|
Modifier and Type | Field and Description |
---|---|
private static ContextLocal<NativeInvoker.WorkArea> |
ctxt
Stores context local instances of the remote memory manager proxy.
|
Modifier | Constructor and Description |
---|---|
private |
NativeInvoker()
Instances of this class cannot be constructed.
|
Modifier and Type | Method and Description |
---|---|
private static int |
calcNumArguments(java.util.List<Parameter> defs)
Return back the non-negative number of arguments for this native API call by processing
the parameter definitions and excluding any RETURN parameter that is found.
|
private static boolean |
checkIntegerRange(java.lang.String type,
java.lang.Class<?> cls,
java.lang.Object arg)
Check if the given argument (or if it is an array, if the argument's elements) is within a
valid range for the type specified.
|
private static boolean |
checkIntegerRangeWorker(java.lang.String type,
long value)
Check if the given value is within a valid range for the type specified.
|
private static boolean |
checkModeAndType(java.lang.String pname,
java.lang.String iename,
Parameter parm,
char runmode,
java.lang.Class<?> cls)
This drives the data type and mode checking for a given argument and will generate errors
in a 4GL compatible manner.
|
private static boolean |
checkUnknown(java.lang.String pname,
java.lang.String iename,
java.lang.String mode,
java.lang.Class<?> cls,
java.lang.Object arg,
BaseNativeType bnt)
This drives the unknown, uninitialized and empty string checking for a given argument
and generates errors in a 4GL compatible manner.
|
private static boolean |
checkUnknownWorker(java.lang.String pname,
java.lang.String iename,
java.lang.String mode,
java.lang.Class<?> cls,
java.lang.Object arg,
boolean array,
BaseNativeType bnt)
This checks a single argument or a single argument array element to detect if it is
unknown or empty string and generate errors in a 4GL compatible manner.
|
private static void |
copyDataIn(java.lang.String type,
java.lang.String mode,
java.lang.Class<?> cls,
java.lang.Object arg,
BaseNativeType bnt)
Copy the data for the given INPUT or INPUT-OUTPUT argument (or if it is an array, the
argument's elements) into the container for transport to the client.
|
private static void |
copyDataInWorker(java.lang.String type,
java.lang.String mode,
java.lang.Class<?> cls,
java.lang.Object arg,
BaseNativeType bnt,
boolean array)
Copy the data for the given argument into the container for transport to the client.
|
private static boolean |
copyDataOut(java.lang.String type,
java.lang.Class<?> cls,
boolean ret,
BaseNativeType bnt,
java.lang.Object arg)
Copy the data for the given INPUT-OUTPUT, OUTPUT or RETURN descriptor (or if it is an
array, the array elements) into the argument.
|
private static boolean |
copyDataOutWorker(java.lang.String type,
java.lang.Class<?> cls,
boolean ret,
BaseNativeType bnt,
java.lang.Object arg,
boolean array)
Copy the data back into the given argument from the container for transport to the client.
|
private static BaseNativeType |
createScalarInstance(java.lang.String type,
java.lang.String mode,
boolean handleTo)
Instantiate a placeholder for a single scalar parameter and configure it based on the
type and mode.
|
private static void |
fixupArrays(java.lang.Class<?>[] signIn,
java.lang.Class<?>[] signOut,
java.lang.Object[] argsIn,
java.lang.Object[] argsOut)
Eliminate any use of the OutputExtentParameter container class and replace it with the
actual array references.
|
private static void |
fixupNonWrappers(java.lang.Class<?>[] signature,
java.lang.Object[] args)
Fixup any input parameters which were passed as literals in the 4GL, which emitted
as Java literals instead of BDT wrappers.
|
private static void |
genCharUnknownErr(boolean force)
Generate an character or longchar value cannot be unknown error.
|
private static void |
genEntrypointErr(java.lang.String funcname,
int ordinal)
Generate a missing entrypoint error.
|
private static void |
genForcableError(int num,
java.lang.String spec,
boolean force)
Generate an error that can optionally not be suppressed by NO-ERROR.
|
private static void |
genIndeterminateArrayErr()
Generate an indeterminate array parameter error.
|
private static void |
genInputUnknownErr(boolean force)
Generate an input value cannot be unknown error.
|
private static void |
genLibraryLoadErr(java.lang.String libname,
int platform)
Generate a library load error.
|
private static void |
genMismatchingModeErr(java.lang.String pname,
java.lang.String iename)
Generate a mismatching mode error.
|
private static void |
genMismatchingTypeErr(java.lang.String pname,
java.lang.String iename)
Generate a mismatching type error.
|
private static void |
genNoArrayForReturnErr()
Generate an cannot pass an array variable for a RETURN parameter error.
|
private static void |
genUninitMemptrErr(java.lang.String pname,
java.lang.String iename)
Generate an uninitialized MEMPTR error.
|
private static boolean |
inboundProcessing(java.lang.String pname,
java.lang.String iename,
java.util.List<Parameter> defs,
java.lang.Class<?>[] signature,
java.lang.String modetxt,
Signature briefcase,
java.lang.Object... args)
Checks the passed parameters (and their values) against the definition and raises errors
to match the behavior of the 4GL, if OK the data will be copied into the descriptors for
transport.
|
private static void |
initializeBriefcase(java.util.List<Parameter> defs,
java.lang.Class<?>[] signature,
Signature briefcase,
java.lang.Object... args)
Analyze the required parameter signature for the function and the passed arguments and
use that information to setup the initial configuration of the briefcase.
|
static void |
invoke(java.lang.String libname,
java.lang.String pname,
java.lang.String iename,
java.lang.Class<?>[] signInput,
java.lang.String modes,
java.lang.Object... argsInput)
Invoke the defined native API call in a manner that is compatible with how the 4GL behaves.
|
private static void |
outboundProcessing(java.util.List<Parameter> defs,
java.lang.Class<?>[] signature,
Signature briefcase,
java.lang.Object... args)
Attempts to copy back all data (from the descriptors used for transport back to the
actual wrapper parameters passed in) that should be copied back, raising errors
to match the behavior of the 4GL when necessary.
|
static void |
release(java.lang.String libname)
Attempts to unload the specified library from memory (this is the implementation of the
RELEASE EXTERNAL statement).
|
private static final ContextLocal<NativeInvoker.WorkArea> ctxt
private NativeInvoker()
public static void invoke(java.lang.String libname, java.lang.String pname, java.lang.String iename, java.lang.Class<?>[] signInput, java.lang.String modes, java.lang.Object... argsInput)
libname
- The library name where this native procedure should be found.pname
- The legacy name of the external procedure from which this API is being called.iename
- The internal-entry name being called which is usually the same as the entry
point name in the library except where an ordinal is being used.signInput
- The signature represented by the caller's passed arguments. This is NOT the same
as the actual signature of native API to be called. This will be compared to the
native API's required signature and errors will be raised as needed.modes
- An encoded string with the mode of each RUN parameter specified as a character
in the string. This is what was defined on the RUN statement NOT what was
defined in the PROCEDURE EXTERNAL.argsInput
- Arguments that were passed (at runtime) to be the inputs to (and receive the
outputs from) the API call.public static void release(java.lang.String libname)
libname
- The name of the library to attempt to unload.private static void fixupArrays(java.lang.Class<?>[] signIn, java.lang.Class<?>[] signOut, java.lang.Object[] argsIn, java.lang.Object[] argsOut)
signIn
- The signature represented by the caller's passed arguments.signOut
- The fixed signature.argsIn
- Arguments that were passed (at runtime) to be the inputs to (and receive the
outputs from) the API call.argsOut
- The fixed arguments.private static void fixupNonWrappers(java.lang.Class<?>[] signature, java.lang.Object[] args)
At this time there is no actual checking of whether this is really an input mode parm or what the exact type should be. If there is a mismatch on the mode, then the caller has coded something that can never receive an update and they will have to figure that out themselves (but it should never happen in converted code since the 4GL disallows literals except for input parms). If there is a type mismatch, then it will trigger a failure downstream in a manner that is 4GL compatible.
signature
- The signature represented by the caller's passed arguments. This will be edited
directly to fixup any issues.args
- Arguments that were passed (at runtime) to be the inputs to (and receive the
outputs from) the API call. This will be edited directly to fixup any issues.private static boolean inboundProcessing(java.lang.String pname, java.lang.String iename, java.util.List<Parameter> defs, java.lang.Class<?>[] signature, java.lang.String modetxt, Signature briefcase, java.lang.Object... args)
The following checks are done (in order):
This code (and its downstream workers) also handles the proper setup of the descriptors for the return value and the parameters. Those descriptors define whether the particular parameter needs to be passed as a pointer, whether it copies data back and other metadata as well as containing the actual value(s) to be transported to the client.
The complexity and quirkiness of the error checking naturally makes this the proper place to setup the descriptors (including copying in the input data).
pname
- The legacy name of the external procedure from which this API is being called.iename
- The internal-entry name being called which is usually the same as the entry
point name in the library except where an ordinal is being used.defs
- Parameter definitions. This defines the required signature of the actual native
API as defined by a converted 4GL PROCEDURE EXTERNAL
statement. As
such it may or may not match reality, but it is what the 4GL uses for error
checking (and there isn't anything better that we can do).signature
- The class list represented by the caller's passed arguments (determined at
runtime). This is NOT the same as the actual signature of native API to be
called. This will be compared to the native API's required signature and errors
will be raised as needed.modetxt
- An encoded string with the mode of each RUN parameter specified as a character
in the string. This is what was defined on the RUN statement NOT what was
defined in the PROCEDURE EXTERNAL.briefcase
- The set of return value and parameter descriptors which should be setup for
transport to the client. This is initially passed as an empty instance and
if no errors are encountered, it will be fully configured for transport to the
client on return.args
- Arguments that were passed (at runtime) to be the inputs to (and receive the
outputs from) the API call.true
to cause a silent return from the calling method. Of course, if
and error has been raised, then the exception will be unwinding the stack and the
return won't matter. But in the case where silent error mode is enabled (the 4GL
NO-ERROR
case), we must return back silently.private static void initializeBriefcase(java.util.List<Parameter> defs, java.lang.Class<?>[] signature, Signature briefcase, java.lang.Object... args)
defs
- Parameter definitions. This defines the required signature of the actual native
API as defined by a converted 4GL PROCEDURE EXTERNAL
statement.signature
- The class list represented by the caller's passed arguments (determined at
runtime). This is NOT the same as the actual signature of native API to be
called. This will be compared to the native API's required signature and errors
will be raised as needed.briefcase
- The set of return value and parameter descriptors which should be setup for
transport to the client. This is initially passed as an empty instance.args
- Arguments that were passed (at runtime) to be the inputs to (and receive the
outputs from) the API call.private static int calcNumArguments(java.util.List<Parameter> defs)
defs
- Parameter definitions. This defines the required signature of the actual native
API as defined by a converted 4GL PROCEDURE EXTERNAL
statement.private static BaseNativeType createScalarInstance(java.lang.String type, java.lang.String mode, boolean handleTo)
type
- The 4GL "DLL" data type.mode
- The 4GL parameter mode (e.g. INPUT).handleTo
- true
if HANDLE TO was specified.private static boolean checkUnknown(java.lang.String pname, java.lang.String iename, java.lang.String mode, java.lang.Class<?> cls, java.lang.Object arg, BaseNativeType bnt)
checkUnknownWorker(java.lang.String, java.lang.String, java.lang.String, java.lang.Class<?>, java.lang.Object, boolean, com.goldencode.p2j.library.BaseNativeType)
for the core processing.pname
- The legacy name of the external procedure from which this API is being called.iename
- The internal-entry name being called which is usually the same as the entry
point name in the library except where an ordinal is being used.mode
- "INPUT", "INPUT-OUTPUT", "OUTPUT" or "RETURN".cls
- The data type of the argument that was passed, which may be an array.arg
- The actual argument instance that was passed, which may be an array.bnt
- The descriptor for this scalar parameter or for an array. Some cases of
unknown value, uninitialized variable or empty string will cause the normal
copy back behavior to be silently ignored instead of raising an error. This
method will edit the descriptor(s) as needed based on the actual value passed.true
to cause a silent return from the calling method.private static boolean checkUnknownWorker(java.lang.String pname, java.lang.String iename, java.lang.String mode, java.lang.Class<?> cls, java.lang.Object arg, boolean array, BaseNativeType bnt)
checkUnknown(java.lang.String, java.lang.String, java.lang.String, java.lang.Class<?>, java.lang.Object, com.goldencode.p2j.library.BaseNativeType)
.pname
- The legacy name of the external procedure from which this API is being called.iename
- The internal-entry name being called which is usually the same as the entry
point name in the library except where an ordinal is being used.mode
- "INPUT", "INPUT-OUTPUT", "OUTPUT" or "RETURN".cls
- The data type of the argument that was passed, which may be an element of an
array.arg
- The actual argument instance that was passed, which may be an element of an
array.array
- true
if this instance was an element of an array.bnt
- The descriptor for this scalar parameter (or array element). Some cases of
unknown value, uninitialized variable or empty string will cause the normal
copy back behavior to be silently ignored instead of raising an error. This
method will edit the descriptor as needed based on the actual value passed.true
to cause a silent return from the calling method.private static boolean checkModeAndType(java.lang.String pname, java.lang.String iename, Parameter parm, char runmode, java.lang.Class<?> cls)
pname
- The legacy name of the external procedure from which this API is being called.iename
- The internal-entry name being called which is usually the same as the entry
point name in the library except where an ordinal is being used.parm
- The parameter definition.runmode
- 'I' for "INPUT", 'U' for "INPUT-OUTPUT" or 'O' for "OUTPUT". "RETURN" parameters
are passed at runtime as "OUTPUT").cls
- The data type of the argument that was passed (or the type of the element of the
array that was passed, which is the type to be considered.true
to cause a silent return from the calling method.private static boolean checkIntegerRange(java.lang.String type, java.lang.Class<?> cls, java.lang.Object arg)
BYTE: -128 through 255 SHORT: -32768 through 32767 UNSIGNED-SHORT: 0 through 65535 LONG: -2147483648 through 2147483647 UNSIGNED-LONG: 0 through 4294967295
type
- The library function's parameter type as defined in the DEFINE PARAMETER
statement.cls
- The class of the argument, which may be an array type.arg
- The argment to be checked.true
if the value is out of bounds.private static boolean checkIntegerRangeWorker(java.lang.String type, long value)
BYTE: -128 through 255 SHORT: -32768 through 32767 UNSIGNED-SHORT: 0 through 65535 LONG: -2147483648 through 2147483647 UNSIGNED-LONG: 0 through 4294967295
type
- The library function's parameter type as defined in the DEFINE PARAMETER
statement.value
- The value to be checked.true
if the value is out of bounds.private static void copyDataIn(java.lang.String type, java.lang.String mode, java.lang.Class<?> cls, java.lang.Object arg, BaseNativeType bnt)
OUTPUT parameters that are passed by pointer must also have their data copied in.
type
- The library function's parameter type as defined in the DEFINE PARAMETER
statement.mode
- The parameter's mode (e.g. INPUT, INPUT-OUTPUT, OUTPUT, RETURN).cls
- The class of the argument, which may be an array type.arg
- The argment to be copied from.bnt
- The target to which the data will be copied.private static void copyDataInWorker(java.lang.String type, java.lang.String mode, java.lang.Class<?> cls, java.lang.Object arg, BaseNativeType bnt, boolean array)
type
- The library function's parameter type as defined in the DEFINE PARAMETER
statement.mode
- The parameter's mode (e.g. INPUT, INPUT-OUTPUT, OUTPUT, RETURN).cls
- The class of the argument.arg
- The argment to be copied from.bnt
- The target to which the data will be copied.array
- true
if this is an array element.private static void outboundProcessing(java.util.List<Parameter> defs, java.lang.Class<?>[] signature, Signature briefcase, java.lang.Object... args)
defs
- Parameter definitions. This defines the required signature of the actual native
API as defined by a converted 4GL PROCEDURE EXTERNAL
statement. As
such it may or may not match reality, but it is what the 4GL uses for error
checking (and there isn't anything better that we can do).signature
- The class list represented by the caller's passed arguments (determined at
runtime). This is NOT the same as the actual signature of native API to be
called. This will be compared to the native API's required signature and errors
will be raised as needed.briefcase
- The set of return value and parameter descriptors which should be setup for
transport to the client. This is initially passed as an empty instance and
if no errors are encountered, it will be fully configured for transport to the
client on return.args
- Arguments that were passed (at runtime) to be the inputs to (and receive the
outputs from) the API call.private static boolean copyDataOut(java.lang.String type, java.lang.Class<?> cls, boolean ret, BaseNativeType bnt, java.lang.Object arg)
type
- The library function's parameter type as defined in the DEFINE PARAMETER
statement.cls
- The class of the argument, which may be an array type.ret
- true
if this is a RETURN parameter.bnt
- The descriptor from which to copy.arg
- The target to which the data will be copied.true
if all processing occurred without error or false
if further outbound processing should be silently (and immediately) aborted.private static boolean copyDataOutWorker(java.lang.String type, java.lang.Class<?> cls, boolean ret, BaseNativeType bnt, java.lang.Object arg, boolean array)
type
- The library function's parameter type as defined in the DEFINE PARAMETER
statement.cls
- The class of the argument.ret
- true
if this is a RETURN parameter.bnt
- The descriptor from which to copy.arg
- The target to which the data will be copied.array
- true
if this is related to the processing of an element in an
array, false
for a scalar variable.true
if all processing occurred without error or false
if further outbound processing should be silently (and immediately) aborted.private static void genIndeterminateArrayErr()
private static void genNoArrayForReturnErr()
private static void genInputUnknownErr(boolean force)
force
- true
to throw the error even in silent mode.private static void genCharUnknownErr(boolean force)
force
- true
to throw the error even in silent mode.private static void genForcableError(int num, java.lang.String spec, boolean force)
num
- The 4GL error number.spec
- The 4GL error text.force
- true
to throw the error even in silent mode.private static void genUninitMemptrErr(java.lang.String pname, java.lang.String iename)
pname
- The legacy name of the external procedure from which this API is being called.iename
- The internal-entry name being called which is usually the same as the entry
point name in the library except where an ordinal is being used.private static void genMismatchingModeErr(java.lang.String pname, java.lang.String iename)
pname
- The legacy name of the external procedure from which this API is being called.iename
- The internal-entry name being called which is usually the same as the entry
point name in the library except where an ordinal is being used.private static void genMismatchingTypeErr(java.lang.String pname, java.lang.String iename)
pname
- The legacy name of the external procedure from which this API is being called.iename
- The internal-entry name being called which is usually the same as the entry
point name in the library except where an ordinal is being used.private static void genLibraryLoadErr(java.lang.String libname, int platform)
libname
- The name of the library that failed to be loaded.platform
- A LibraryManager constant defining the platform on which the client was running.private static void genEntrypointErr(java.lang.String funcname, int ordinal)
funcname
- The name of the function that failed to be loaded.ordinal
- The ordinal of the function that failed to be loaded or -1 if no ordinal was
specified.