Walnut/Ordinary Programming/Interfacing to Java

From Erights

(Difference between revisions)
Jump to: navigation, search
(Importing classes from the Java API)
(Arrays and Java types)
 
(5 intermediate revisions not shown)
Line 55: Line 55:
====Speaking to Java objects with superclass/subclass overloaded methods====
====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 <span class="e">''E''</span> 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. <span class="note" style="color:red">coercion causes same problem</span>In that case, we need to revert to a more descriptive messaging convention.
+
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 <span class="e">E</span> 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.
-
We introduced the E.call() function earlier for communicating with E objects. It can also be used to call Java objects and to specify the signature of an overloaded method with the types of the parameters. 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:
+
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:
<pre>
<pre>
Line 66: Line 66:
  # example problem: <IllegalArgumentException: ...>
  # example problem: <IllegalArgumentException: ...>
   
   
-
  ? E.call(out, "print(String)", ["abc"])</nowiki>
+
  ? out."print(String)"("abc")</nowiki>
</pre>
</pre>
 +
 +
In general, quotes can be used to name a verb which is not a valid identifier in E syntax. Here, the verb is exactly “<code>print(String)</code>”.
(Where should the following explanation go?)
(Where should the following explanation go?)
Line 79: Line 81:
<pre>
<pre>
-
  <nowiki>? def myLabel := E.call(<swing:makeJLabel>, "run(String)",["label text"])</nowiki>
+
  <nowiki>? def myLabel := <swing:makeJLabel>."run(String)"("label text")</nowiki>
</pre>
</pre>
Line 85: Line 87:
<pre>
<pre>
-
  E.call(javaObject, "method(String, int)", ["abc", 23])
+
  javaObject."method(String, int)"("abc", 23)
</pre>
</pre>
-
====Arrays and primitive types====
+
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:
-
 
+
-
It is possible to make Java arrays of Java primitive types, as in this example:
+
<pre>
<pre>
 +
def Math := <unsafe:java.lang.makeMath>
 +
def abs(value) {
 +
  return Math."abs(double)"(value)
 +
}
 +
</pre>
-
<nowiki># E sample
+
====Arrays and Java types====
-
def makeFlexList := <elib:tables.makeFlexList>
+
-
def byteArray := makeFlexList.fromType(<type:byte>, 300)
+
-
byteArray.setSize(300)
+
-
byteArray[0] := 3</nowiki>
+
-
</pre>
+
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>
 +
 
 +
====Promises====
 +
 
 +
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"]
-
Here we have created a 300-element editable array of bytes. The individual elements can be accessed with square bracket notation.
+
? <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>
-
<font color="#FF0000">XXX Now that this example has been corrected, does it still serve its purpose? Also, it's not technically correct to say this makes a Java array. It makes an E FlexList, which, on E-on-Java, currently happens to be implemented by wrapping a Java array. However, if your program depends on this fact, it is probably broken. </font>
+
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====
====Java Adapters and Interfaces====

Latest revision as of 12:12, 12 September 2011


Contents

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>()
 myVector.addElement("abc")

 #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
 <unsafe:java.util.makeCalendar>.getYEAR()

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>

Promises

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