6.2. Java sites

Essential to Orc's role as an orchestration language is Orc's interaction with its host platform, which in this implementation is the Java virtual machine (JVM). In addition to calling Orc sites per se, Orc programs can access arbitrary Java classes using the import class declaration. Values in Java fields, values returned from Java methods, and values returned from Java constructors may be used in Orc programs just as any other Orc value.

6.2.1. Java classes

Java classes are named in an Orc program using the import class declaration. In the scope of such a declaration, the declared name is bound to a value that acts as a proxy for the Java class. This class proxy may be called as an Orc site, which invokes the Java class constructor corresponding to the arguments of the site call. The class proxy also presents the class static methods and class static fields in the same manner as an Orc record, with keys corresponding to the Java class members' names. Class methods appear as record elements that are sites, and are invoked by projecting the record element using the dot notation and calling the site. Fields appear as record elements that are references, and are accessed and assigned by projecting the record element using the dot notation and using Orc's ? and := operators.

Note that Java allows fields and methods with identical names to be members of the same class. In this case, Orc's Java class proxy resolves from the usage of a record element whether to access the field or method.

Orc Java class proxies are not true Orc record values, although they appear syntactically as if they are.

Java classes are loaded from the Orc site classpath, which may be specified as a setting of the Orc runtime engine; for example via a command-line option or an Eclipse project property. If the class is not found on the Orc site classpath, the loading attempt continues using the normal Java classpath.

6.2.2. Java objects

Java objects may be returned by any Orc site call, including constructor or class static method invocations of an Orc Java class proxy. Java objects' methods and fields appear in the same manner as an Orc record with keys corresponding to the members' names. Methods appear as record elements that are sites, and are invoked by projecting the record element using the dot notation and calling the site. Fields appear as record elements that are references, and are accessed and assigned by projecting the record element using the dot notation and using Orc's ? and := operators. If a Java object is called as a site without projecting a member, the method name apply is implicitly used.

Note that Java allows fields and methods with identical names to be members of the same class. In this case, Orc's Java object proxy attempts to resolve from the usage of a record element whether to access the field or method.

If a field's value is a class with a member named read this member will be invoked when an Orc program accesses that field with the ? operator. Similarly, if a field's value is a class with a member named write, this member will be invoked when an Orc program assigns a new value to that field with the := operator. Note that this is a potentially surprising name conflict.

6.2.3. Java value conversions

When interacting with Java classes and objects, Orc performs some conversions of values passed to and from the Java code. Specifically, Orc applies conversions to the following:

  • Arguments of invoked constructors and methods

  • Return values of invoked constructors and methods

  • Accessed values from fields

  • Assigned values to fields

  • Accessed values from array components

  • Assigned values to array components

The conversions applied are the following:

  • void Java methods return signal in Orc.

  • Orc integers are converted to Java Byte, Short, Integer, Long, Float, or Double, as needed.

  • Orc numbers are converted to Java Float or Double, as needed.

  • Java Byte, Short, Integer, and Long are converted to Orc integers.

  • Java Float and Double are converted to Orc numbers.

  • Java primitive values are boxed and unboxed as needed, per The Java Language Specification §5.1.7 and §5.1.8.

  • Java widening primitive conversions are applied as needed, per The Java Language Specification §5.1.2.

Note that Orc integers and numbers represent a larger range of values than the standard Java numeric types. If an integer conversion is applied to an out-of-range value, the result is the least significant bits of the out-of-range value. This will change the magnitude of the number and may change its sign. If a floating-point conversion is applied to an out-of-range value, the result is positive or negative infinity, as appropriate.

6.2.4. Java method and constructor invocation

Orc invokes a Java method or constructor by closely approximating the Java method invocation rules specified in The Java Language Specification §15.12. This is only an approximation, because Orc performs Java compile-time steps at run time using Java's reflection facilities, and therefore has a different view of the types of values than the Java compiler. However, in most cases, this difference has no effect. At present, Orc does not recognize Java variable arity methods. (In practice, this is a very rarely used feature of Java.)

Orc has a Java stack trace option, which may be specified as a setting to the Orc runtime engine (for example, via a command-line option or an Eclipse run configuration setting). This may be helpful when debugging Java invocations.

6.2.5. Java arrays

Java arrays are accessible in Orc. To refer to a component of a Java array, follow the array value with a nonnegative integer-valued expression in parenthesis. Java arrays are zero-origin. Array components appear as references in Orc. Their values may be accessed and assigned using Orc's ? and := operators. The Java length pseudo-field of arrays is available in Orc as length?.

6.2.6. Examples

Construct a Java object, and invoke methods
{- Name a Java class and use it to invoke object methods -}
import class URL = "java.net.URL"

{- Create an instance-}
val googleUrl = URL("http://www.google.com/")

{- Invoke some methods -}
googleUrl.openConnection().getResponseMessage()

{-
OUTPUT:
"OK"
-}
Accessing class members
{- Access Java's String and Boolean classes -}

import class JavaBoolean = "java.lang.Boolean"
import class JavaString = "java.lang.String"

-- Static field access
JavaBoolean.TRUE? |

-- Constructor invocation
JavaBoolean("true") |

-- Static method access
JavaBoolean.parseBoolean("true") |

-- Overloading and Orc-Java conversion -- String.valueOf(double) is invoked
JavaString.valueOf(2e108)

{-
OUTPUT:PERMUTABLE
true
true
true
"2E+108"
-}
No-arg constructor invocation, field assignment, and field dereference
{- Constructor invocation -} 

import class FieldTestClass = "org.omg.CORBA.portable.ServantObject"

-- No-arg constructor invocation
FieldTestClass() >testInstance>

-- Field assignment
testInstance.servant := "test 4" >>

-- Field derefence
testInstance.servant?

{-
OUTPUT:
"test 4"
-}
Integer conversion overflow
{- Demonstrate an Orc-to-Java integer conversion of an out-of-range value -}

import class JavaInteger = "java.lang.Integer"

val x = 1230000000000000000456789

JavaInteger.valueOf(x)

{-
OUTPUT:
-1530464171
-}

6.2.7. Related Links

Related Tutorial Sections