 |
Free EcmaScript Interpreter.
A JavaScript interpreter written
in Java. |
Language extensions - JavaAccess |
The JavaAccess extension is always loaded by the interactive interpreter,
and allows the user to directly access any Java class reachable via the
CLASSPATH.
It is largely compatible with the Netscape "Packages" capability.
The example directory contains various usage of JavaAccess. The Netscape
JavaScript
reference is a good source for further information.
See the Java library section on how to access
EcmaScript from a java program.
See the Event Handler section on how to create
Java event handlers in EcmaScript.
Objects defined by the JavaAccess extension
This extensions includes 5 new objects:
-
Packages
-
A JavaPackages object, representing the root of all Java packages.
When a property of a Packages object is accessed, a corresponding
JavaPackages
object is created. For example "Packages.EDU.nowhereUni" creates
a JavaPackages for "EDU.nowhereUni". A JavaPackages
is just a name prefix, it does not have to match a real package (the package
must be a real one when a class of the package is used).
-
It is therefore easy to create package abreviation like:
-
tools = Packages.EDU.puddingtonUni.tools.
-
In addition a Packages can be used to create a class loader, to
load classes from a directory root or from a jar file. To create such a
loader call Packages as a function, specifying the directory or
jar file name. For example:
-
new Packages("java/graphics/classes").graphics.line
-
refers to a class 'graphics.line' in a subdirectory of java/graphics/classes.
Packages("C:/library/tools.jar")
would similarly create a new root for classes from the specified tools
jar file.
-
A package cannot be created if the Packages object is the expression
of a with statement - simply create the packages you need before
the with statement!
-
Beans
-
A JavaBeans object, representing the root of all Java beans. When
a property of a Beans object is accessed, a corresponding JavaBeans
object is created. For example "Beans.java.awt.Button" refer to
an awt button used as a bean. A new Beans root can be created by calling
Beans as a function, specifying jar file or a directory root, for example:
-
JugglerJar = Beans(bdkHome+"juggler.jar")
-
The bean can then be created by specifying it relatively the the bean root,
as in 'new JugglerJar.sunw.demo.juggler.Juggler()'. Even
if it loads the bean from a jar file with a manifest, Beans does
not test if the class was indeed declared as a bean, it will attempt to
instantiate any specified class as a bean.
-
When declared as a bean, only the properties and method described by the
corresponding BeanInfo (see Sun documentation on beans) can be
accessed. Bean properties can be accessed as EcmaScript properties (FESI
will use the appropriate getter or setter routines, it will not directly
access the fields, even if public).
-
java
-
Equivallent to Packages.java, to make access to Java language
functions easier.
-
javaTypeOf
-
A function which returns the name of the class of the java object
which would be created, if the value were passed to a Java method. Useful
to debug access to overloaded functions. The class JSWrapper is
used to package EcmaScript objects as a Java object if no better type can
be found, and is therefore returned if this function is called for a EcmaScript
built-in object. Elementary EcmaScript values are transformed in the smallest
type containing them (1234 will be a java.lang.Short).
-
loadExtension
-
A function to load an EcmaScript extension programmatically, giving the
class name as a parameter, for example loadExtension("FESI.Extensions.FileIO").
Reloading an already loaded extension has no effect.
The command @describe of the interpreter is very useful to examine
the characteristic of a java object. Its class, methods and fields are
listed, including the properties if the object is used as a bean.
Accessing properties or fields of a Java or Corba
object
The following mechanism is used to access properties or fields of an object
created by the Packages mechanism or received from a Java function
(including CORBA objects received as a Java object from a Java function).
-
First a public Java field with the same name si looked up. If it is found,
then it is directly accessed (any setter or getter function is ignored).
-
Fields with a name starting with "on" are handled specially: if they do
not exist in an object, they are interpreted as a request to setup an event
handler (see the event handling page for details).
-
If the field is not found or not public, then bean introspection is used
to find the property. If is is found by introspection then the getter or
setter routines is used.
-
As a last ressort a routine with the name of the property is looked up
as a setter (void with 1 argument of the same type) or getter (no argument,
returning a value). This last method is compatible with CORBA objects accessed
from Java.
The properties of objects declared as Bean (using the Beans creation mechanism)
are only looked up using bean introspection.
It is naturally always possible to call a setter or getter routine directly.
Creating Java objects
Once the JavaAccess package is loaded, it is possible to create new Java
objects, for example:
cal = new java.util.GregorianCalendar();
The Java objects can be called almost as native EcmaScript objects. Strings,
dates and numeric values are converted automatically between EcmaScript
and Java. Non convertible objects are wrapped, that is a Java object (as
a Calendar) is represented by a wrapper object in EcmaScript. This wrapper
objects takes care of calling the native functions or accessing the properties.
If the wrapper is given back to a Java routine, then the wrapped (Java
native) object is used as its value. In case of overloaded functions, the
wrapper will attempt to find a suitable instance, possibly widening numbers
or converting single character Strings to a Character if needed.
Array returned from a java routine as wrapped as an array and can be
manipulated as an array. If the wrapped array is passed back to a Java
routine, the array will be unwrapped. An EcmaScript Array can
be used where a java array is required, if all elements of the
array can be converted to the target array component type. In that case
a copy of the array is used as a parameter. This may be time consuming
for very large array. If an array must be shared between Java and EcmaScript,
it must be created in Java.
If a java class or object name conflicts with an EcmaScript keyword,
you must use the dynamic indexing notation, as for example in:
Because the notation 'java.lang.System.in' would create a syntax
error, 'in' being a keyword in EcmaScript.
Using enumerators
It is possible to directly use Java enumerators in a "for in" construction.
For example:
// Get the properties
properties = java.lang.System.getProperties();
// List them, using a java enumerators
for (key in properties.keys()) {
value = properties.get(key);
writeln ("Property '" , key, " = '", value, "'");
}
Constructors used as a function
If a Java class name is used as a function, the corresponding constructor
is called if it exists - for example:
cal=java.util.GregorianCalendar()
There is one difference for elementary values. In principle values which
can be converted to an EcmaScript type are automatically converted. For
example str=java.lang.String("Hello") will create an EcmaScript
string, not a wrapped Java String. However if new is
used with these basic types, a wrapper to a Java String will be
returned instead. That wrapper is likely to be converted to an EcmaScript
string at the first usage, but this may be convenient to force the type
of a variable to solve a delicate overloading conflicts. For example: javaObj.append(new
java.lang.Long(23)) will direct EcmaScript to look at a variant of
the append functionwith a Long parameter (rather than
say a Double).
It is possible to define event processing routines with FESI,
see the FESI event handling page for details.
Limitations
Indexed beans properties are not currently supported, unless the full array
can be accessed and set at once.
Information on beans and event handling is kept with the wrapper
of the object. If a bean or a java object is created or received by FESI,
passed to a Java routine from FESI and, then returned to FESI
(for example as the return value), it will receive a new wrapper. This
may create some confusion, especially regarding the equality of such objects.
The recommendation is to always use the original reference of a bean or
Java object in FESI.
The selection of the routine is based on some heuristic to solve overloading.
You may have to use @debugJavaAccess in the interpreter if the
routine called is not the expected one. Because of the difference in model
between the Java and EcmaScript typing, it is not always possible to make
a unique conversion. In pratice these case are rare and if needed a wrapper
routine or an extension may be created.
The following limitation is non obvious (see bug (4090460)
in Sun Java implementation): Invoking a public method on a java object
that is inherited from a non-public class is callable directly but not
via reflection (and therefore not from FESI) when the caller is from a
different package. That problem persists under JDKs 1.1.7B through 1.3beta
on Win98, NT4.0, and SunOS 5.5.1. As a workaround you can make the super
class public or write a wrapper object.
Return to the main page
Last update: 21 October 1999