The Java™ access functions are EGL system functions that allow your generated Java code to access native Java objects and classes; specifically, to access the public methods, constructors, and fields of the native code.
This EGL feature is made possible at run time by the presence of the EGL Java object space, which is a set of names and the objects to which those names refer. A single object space is available to your generated program and to all generated Java code that your program calls locally, whether the calls are direct or by way of another local generated Java program, to any level of call. The object space is not available in any native Java code.
To store and retrieve objects in the object space, you invoke the Java access functions. Your invocations include use of identifiers, each of which is a string that is used to store an object or to match a name that already exists in the object space. When an identifier matches a name, your code can access the object associated with the name.
Each of the arguments you pass to a method (and each value that you assign to a field) is mapped to a Java object or primitive type. Items of EGL primitive type CHAR, for example, are passed as objects of the Java String class. A cast operator is provided for situations in which the mapping of EGL types to Java types is not sufficient.
When you specify a Java name, EGL strips single- and double-byte blanks from the beginning and end of the value, which is case sensitive. The truncation precedes any cast. This rule applies to string literals and to items of type CHAR, DBCHAR, MBCHAR, or UNICODE. No such truncation occurs when you specify either a method argument or field value (for example, the string " my data " is passed to a method as is), unless you cast the value to objID or null.
The next table describes all the valid mappings.
Category of Argument | Examples | Java Type | |
---|---|---|---|
A string literal or an item of type CHAR, DBCHAR, MBCHAR, or UNICODE | No cast | "myString" |
java.lang.String |
Cast with objId, which indicates an identifier | (objId)"myId" x = "myId"; (objId)X |
The class of the object to which the identifier refers | |
Cast with null, as may be appropriate to provide a null reference to a fully qualified class | (null)"java. lang.Thread" x = "java.util. HashMap"; (null)x |
The specified class Note: You can't pass in a null-casted
array such as (null)"int[]"
|
|
Cast with char, which means that the first character of the value is passed (each example in the next column passes an "a") | (char)"abc" X = "abc"; (char)X |
char | |
An item of type FLOAT or a floating point literal | No cast | myFloatValue |
double |
An item of type HEX | No cast | myHexValue |
byte array |
An item of type SMALLFLOAT | No cast | mySmallFloat |
float |
An item of type DATE | No cast | myDate |
java.sql.Date |
An item of type TIME | No cast | myTime |
java.sql.Time |
An item of type TIMESTAMP | No cast | myTimeStamp |
java.sql.Timestamp |
An item of type INTERVAL | No cast | myInterval |
java.lang.String |
Floating point literal | No cast | -6.5231E96 | double |
Numeric item (or non-floating-point literal) that does not contain decimals; leading zeros are included in the number of digits for a literal | No cast, 1-4 digits | 0100 |
short |
No cast, 5–9 digits | 00100 |
int | |
No cast, 9-18 digits | 1234567890 |
long | |
No cast, >18 digits | 1234567890123456789 |
java.math.BigInteger | |
Numeric item Numeric item (or non-floating-point literal) that contains decimals; leading and trailing zeros are included in the number of digits for a literal | No cast, 1–6 digits | 3.14159 |
float |
No cast, 7-18 digits | 3.14159265 |
double | |
No cast, >18 digits | 56789543.222 |
java.math.BigDecimal | |
Numeric item or non-floating-point literal, with or without decimals | Cast with bigdecimal, biginteger, byte, double, float, short, int, long | X = 42; (byte)X (long)X |
The specified primitive type; but if the value is out of range for that type, loss of precision occurs and the sign may change |
Cast with boolean, which means that non-zero is true, zero is false | X = 1; (boolean)X |
boolean |
For details on the internal format of items in EGL, see the help pages on Primitive types.
This section gives examples on how to use Java access functions.
// call the constructor of the Java Date class and // assign the new object to the identifier "date". JavaLib.storeNew( (objId)"date", "java.util.Date" ); // call the toString method of the new Date object // and assign the output (today's date) to the chaItem. // In the absence of the cast (objId), "date" // refers to a class rather than an object. charItem = JavaLib.invoke( (objId)"date", "toString" ); // assign the standard output stream of the // Java System class to the identifier "systemOut". JavaLib.storeField( (objId)"systemOut", "java.lang.System", "out" ); // call the println method of the output // stream and print today's date. JavaLib.invoke( (objID)"systemOut","println",charItem ); // The use of "java.lang.System.out" as the first // argument in the previous line would not have been // valid, as the argument must either be a // an identifier already in the object space or a class // name. The argument cannot refer to a static field.
// assign the name of an identifier to an item of type CHAR valueID = "osNameProperty" // place the value of property os.name into the // object space, and relate that value (a Java String) // to the identifier osNameProperty JavaLib.store((objId)valueId, "java.lang.System", "getProperty", "os.name"); // test whether the property value is non-existent // and process accordingly myNullFlag = JavaLib.isNull( (objId)valueId ); if( myNullFlag == 1 ) error = 27; end
When you work with Java arrays in EGL, use the Java class java.lang.reflect.Array, as shown in later examples and as described in the Java API documentation. You cannot use JavaLib.storeNew to create a Java array because Java arrays have no constructors.
You use the static method newInstance of java.lang.reflect.Array to create the array in the object space. After you create the array, you use other methods in that class to access the elements.
The code that identifies the Class object varies according to whether you are creating an array of objects or an array of primitives. The subsequent code that interacts with the array also varies on the same basis.
// Get a reference to the class, for use with newInstance JavaLib.store( (objId)"objectClass", "java.lang.Class", "forName", "java.lang.Object" ); // Create the array in the object space JavaLib.store( (objId)"myArray", "java.lang.reflect.Array", "newInstance", (objId)"objectClass", 5 );
If you want to create an array that holds a different type of object, change the class name that is passed to the first invocation of JavaLib.store. To create an array of String objects, for example, pass "java.lang.String" instead of "java.lang.Object".
length = JavaLib.invoke( "java.lang.reflect.Array", "getLength", (objId)"myArray" ); i = 0; while ( i < length ) JavaLib.store( (objId)"element", "java.lang.reflect.Array", "get", (objId)"myArray", i ); // Here, process the element as appropriate JavaLib.invoke( "java.lang.reflect.Array", "set", (objId)"myArray", i, (objId)"element" ); i = i + 1; end
int length = myArray.length; for ( int i = 0; i < length; i++ ) { Object element = myArray[i]; // Here, process the element as appropriate myArray[i] = element; }
To create an array that stores a Java primitive rather than an object, use a different mechanism in the steps that precede the use of java.lang.reflect.Array. In particular, obtain the Class argument to newInstance by accessing the static field TYPE of a primitive type class.
// Get a reference to the class, for use with newInstance JavaLib.storeField( (objId)"intClass", "java.lang.Integer", "TYPE"); // Create the array in the object space JavaLib.store( (objId)"myArray2", "java.lang.reflect.Array", "newInstance", (objId)"intClass", 30 );
If you want to create an array that holds a different type of primitive, change the Class name that is passed to the invocation of JavaLib.storeField. To create an array of characters, for example, pass "java.lang.Character" instead of "java.lang.Integer".
length = JavaLib.invoke( "java.lang.reflect.Array", "getLength", (objId)"myArray2" ); i = 0; while ( i < length ) element = JavaLib.invoke( "java.lang.reflect.Array", "getDouble", (objId)"myArray2", i ); // Here, process an element as appropriate JavaLib.invoke( "java.lang.reflect.Array", "setDouble", (objId)"myArray2", i, element ); i = i + 1; end
int length = myArray2.length; for ( int i = 0; i < length; i++ ) { double element = myArray2[i]; // Here, process an element as appropriate myArray2[i] = element; }
Iterator contents = list.iterator(); while( contents.hasNext() ) { Object myObject = contents.next(); // Process myObject }
JavaLib.store( (objId)"contents", (objId)"list", "iterator" ); hasNext = JavaLib.invoke( (objId)"contents", "hasNext" ); while ( hasNext == 1 ) JavaLib.store( (objId)"myObject", (objId)"contents", "next"); // Process myObject hasNext = JavaLib.invoke( (objId)"contents", "hasNext" ); end
// Create a collection from array myArray // and relate that collection to the identifier "list JavaLib.store( (objId)"list", "java.util.Arrays", "asList", (objId)"myArray" );
Next, iterate over list, as shown in the preceding section.
The transfer of an array to a collection works only with an array of objects, not with an array of Java primitives. Be careful not to confuse java.util.Arrays with java.lang.reflect.Array.
Many of the Java access functions are associated with error codes, as described in the function-specific help pages. If the value of the system variable VGVar.handleSysLibraryErrors is 1 when one of the listed errors occurs, EGL sets the system variable sysVar.errorCode to a non-zero value. If the value of VGVar.handleSysLibraryErrors is 0 when one of the errors occurs, the program ends.
Of particular interest is the sysVar.errorCode value "00001000", which indicates that an exception was thrown by an invoked method or as a result of a class initialization.
When an exception is thrown, EGL stores it in the object space. If another exception occurs, the second exception takes the place of the first. You can use the identifier caughtException to access the last exception that occurred.
In an unusual situation, an invoked method throws not an exception but an error such as OutOfMemoryError or StackOverflowError. In such a case, the program ends regardless of the value of system variable VGVar.handleSysLibraryErrors.
int errorType = 0; Exception ex = null; try { java.io.FileOutputStream fOut = new java.io.FileOutputStream( "out.txt" ); } catch ( java.io.IOException iox ) { errorType = 1; ex = iox; } catch ( java.lang.SecurityException sx ) { errorType = 2; ex = sx; }
VGVar.handleSysLibraryErrors = 1; errorType = 0; JavaLib.storeNew( (objId)"fOut", "java.io.FileOutputStream", "out.txt" ); if ( sysVar.errorCode == "00001000" ) exType = JavaLib.qualifiedTypeName( (objId)"caughtException" ); if ( exType == "java.io.IOException" ) errorType = 1; JavaLib.storeCopy( (objId)"caughtException", (objId)"ex" ); else if ( exType == "java.lang.SecurityException" ) errorType = 2; JavaLib.storeCopy( (objId)"caughtException", (objId)"ex" ); end end end