Walnut/Ordinary Programming/Interfacing to Java

From Erights

Jump to: navigation, search


Interfacing to Java

Importing classes from the Java API

We can import a class from the underlying Java virtual machine with the import statement, and speak to the Java object much as we would speak to an E object: replace vector as example

 # E sample
 #create a single vector with a direct call to Java
 def myVector := <unsafe:java.util.makeVector>()

 #create a makeVector function which can be called repeatedly to make more vectors
 def makeVector := <unsafe:java.util.makeVector>
 def vector2 := makeVector()

 # create a shorthand for the java.util package, that gives quick access to all the 
 # classes in java.util
 def <util> := <unsafe:java.util.*>
 def vector3 := <util:makeVector>()

In the example, we showed 3 ways of getting a Java object, which are roughly comparable to the different styles of using "import" in Java. If you just want one vector, you can get it by directly calling the vector constructor. If you plan to make many vectors, you can import the class into a variable. And if you plan to use many classes in a particular package, you can create your own representative for the package that you can use instead of "<unsafe>".

Note that the angle-brackets here are simply syntactic sugar: <util> is short for util__uriGetter and <util:makeVector> is short for util__uriGetter.get("makeVector").

Note also that E prefixes every Java class name with "make". The idea here is to make existing Java classes match the naming conventions of E constructors.

We have now seen 3 uriGetters, file:, unsafe:, and the programmer-defined util:. Four other uriGetters are also predefined, swing: (for accessing javax.swing) and awt: (for accessing java.awt), resource: (for read-only access to resource files such as images, sounds, and static texts), and import:, described next.

The import: uriGetter is similar to unsafe:, except it only imports those parts of the Java API that have been audited for capability security and found to convey no authority (see the Appendix for a definition of "authority").

Put in link, think of better example. Remove vector from the book. Since the Vector class conveys no authority, you should be able to get a vector with import, but currently you can't.

 def vector4 := <unsafe:java.util.makeVector>()

As discussed later with Library Packages and Secure Mobile Code, emakers cannot use unsafe: unless the unsafe__uriGetter is explicitly handed to them. So import: is often useful in these security-aware situations. A complete list of safe versus unsafe classes, and the small percentage of Java API methods which are suppressed for security reasons, are listed in the Appendix.link

<resource> is considered safe, and can therefore be used directly in emakers.

As noted earlier, E does not have an expression to directly represent public static final variables. To use such static finals from a Java class, put parentheses at the end of the variable name, making it syntactically look like a function call, prefix it with "get", uppercase the first letter, and E will get the value for you:

 # E sample

Speaking to Java objects with superclass/subclass overloaded methods

Speaking to Java objects is usually as easy as shown above, where we simply sent myVector an addElement(object) message as if it were an E object. A problem arises with some Java objects if they have overloaded methods for which the only distinguishing mark is the static typing of the parameters in which one of the methods specifies a type that is a superclass of the type in the other method — a rare but not unheard-of situation. XXX coercion causes same problem In that case, we need to revert to a more descriptive messaging convention.

Overloaded methods in Java are presented to E with verbs qualified by the types of the arguments. In this example, we see that the print function for the System.out object is overloaded for both String and Object, with String being a subclass of Object, so the full signature is required:

 ? def out := <unsafe:java.lang.makeSystem>.getOut()
 # value: <a PrintStream>
 ? out.print("abc")
 # example problem: <IllegalArgumentException: ...>
 ?  out."print(String)"("abc")

In general, quotes can be used to name a verb which is not a valid identifier in E syntax. Here, the verb is exactly “print(String)”.

(Where should the following explanation go?) To use an example from awt: or swing:, we need our vat to be running with the AWT event loop. Normally this happens by running in a vat spawned to run a "*.e-awt" file. currentVat.morphInto("awt") asks the current vat to start executing instead in the awt event loop. It returns a promise which resolves to null or broken once this operation succeeds or fails. ? interp.waitAtTop(p) pauses our interpreter (E's read-eval-print loop) until p is resolved.

 ? interp.waitAtTop(currentVat.morphInto("awt"))

Now that that's done, we can proceed to the next example.

 ? def myLabel := <swing:makeJLabel>."run(String)"("label text")

If you encounter one of these special cases that requires multiple parameters, the signatures must be laid out with exact spelling and exact spacing, notably with exactly one space between the comma and the next signature:

 javaObject."method(String, int)"("abc", 23)

Accessing functions in the java.lang.Math class are a particularly interesting case. Some of these functions are overloaded on float, double and perhaps int and long. While E does not support float and has a different view of integers, it still sees these functions as overloaded. Accessing the correct function is simple, if verbose:

def Math := <unsafe:java.lang.makeMath>
def abs(value) {
  return Math."abs(double)"(value)

Arrays and Java types

If you call a Java method which requires an array and you pass in an E list, E will automatically convert it. For example, to create a Java BigInteger from an EList of ints, you can just do:

? def makeBigInteger := <import:java.math.makeBigInteger>
# value: <makeBigInteger>
? def x := makeBigInteger([1, 2])
# value: 258

E automatically converts from its own EList type to the required int[] type in this case.

However, if the Java method took an Object argument then E would pass it an EList directly. You can use E's conversion features from your own Java code using E.as():

import org.erights.e.elib.prim.E;

public class Test {
	public Test(Object obj) {
		System.out.println("obj = " + obj + ", of type " + obj.getClass());

		String[] list = (String[]) E.as(obj, String[].class);

		System.out.println("list = " + list + ", of type " + list.getClass());

When called from E:

? <unsafe:makeTest>(["foo", "bar"])
obj = ["foo", "bar"], of type class org.erights.e.elib.tables.ConstListImpl
list = [Ljava.lang.String;@39cd2b99, of type class [Ljava.lang.String;
# value: <a Test>


Internally, an E promise is an object which, when resolved, holds a pointer to its resolution. From E code, a resolved promise is identical to the resolution, but from Java they are separate objects.

For example (using the Test class above):

? def listVow 
# value: <Resolver>
? bind listVow := ["foo", "bar"]
# value: ["foo", "bar"]
? <unsafe:makeTest>(listVow)
obj = ["foo", "bar"], of type class org.erights.e.elib.ref.SwitchableRef
list = [Ljava.lang.String;@5fc9d050, of type class [Ljava.lang.String;
# value: <a Test>

Notice that we now get a SwitchableRef rather than a ConstListImpl. Using E.as to coerce it to String[] still works, but you can also do it directly using Ref.resolution(vow) (which would get you the ConstListImpl).

Java Adapters and Interfaces

As described earlier, you can use the match[verb,args] construct to aid in writing adapters and other objects that must meet a Java interface specification. E will automatically manipulate the resulting E objects and the java virtual machine so that Java understands that the E object meets the interface specification. It is not possible to make subclasses of Java classes in E. However, because the developers of the Java API have wisely moved aggressively to make sure that interfaces, rather than subclasses, are core to Java object interoperability, there is virtually no Java interfacing goal that cannot be achieved with this machinery.

The Java API versus capability security

A final note: almost all of the objects and methods in the Java API are available in E for version 1.0 through the unsafe_uriGetter; unfortunately very few have been audited sufficiently to be included with the import__uriGetter. In the future, more of the API will be accessible through the import__uriGetter; however, some parts of the Java API will be altered and/or suppressed even in unsafe__uriGetter to achieve a more secure yet easier to use computing framework. This is discussed further in the chapter on Mobile Code. You can see the list of suppressed methods and unsafe classes in the Javadoc.

Personal tools
more tools