The public Java interfaces are exported in the following packages:
com.oracle.solaris.rad.client – The client implementation of the RAD protocol and associated functionality
com.oracle.solaris.rad.connect – The classes for connecting to a RAD instance
RAD instances can communicate through the Connection class. Various factory interfaces are available to get different types of connections to a RAD instance. Each mechanism returns a connection instance that provides a standard interface to interact with RAD. The connection can be closed with the close() method.
You can connect to a local instance by using the Connection.connectUnix() class. An implicit authentication is performed against your user ID and most RAD tasks you request with this connection are performed with the privileges available to your user account.
Example 15 Java Language – Creating a Local RAD Connectionimport com.oracle.solaris.rad.connect.Connection; Connection con = Connection.connectUnix();
When connecting to a remote instance, no implicit authentication is performed. The connection is not established until you authenticate. The com.oracle.solaris.rad.client package provides a utility class (RadPamHandler) which can be used to perform a PAM login. If you provide a locale, username and password, authentication is non-interactive. If locale is null, then C is used.
Here is an example for Remote Connection to a TCP instance on port 7777.
Example 16 Java Language – Creating Remote RAD Connection to a TCP Instance on Port 7777import com.oracle.solaris.rad.client.RadPamHandler; import com.oracle.solaris.rad.connect.Connection; Connection con = Connection.connectTCP("host1", 7777); System.out.println("Connected: " + con.toString()); RadPamHandler hdl = new RadPamHandler(con); hdl.login("C", "user", "password"); // First argument is locale con.close();
You can use a URI to connect to a local or remote RAD instance. You can use the class URIconnection in Java for connecting using a URI. For more information, see Connecting in Python to a RAD Instance by Using a URI.
The following constructors are supported.
public URIConnection(String src) throws IOException { this(src, DEFAULT_SCHEMES); } public URIConnection(String src, Set<String> schemes) throws IOException { } public URIConnection(String src, Set<String> schemes, Set<String> certfiles) throws IOException { }
Use the different constructors depending on how much control you need over the connection.
For methods, the following functions are supported for adding or removing certificates for TLS connections, and connecting and processing PAM information.
public void addCertFile(String certfile) { } public void rmCertFile(String certfile) { } public Connection connect(Credentials cred) throws IOException { } public void processPAMAuth(PAMCredentials cred, Connection con) throws IOException { }
The following utility functions are supported for providing information about a RAD instance:
public String getAuth()
public String getCredClass()
public void setCredClass(String klass) throws IOException
public String getHost()
public String getPath()
public int getPort()
public String getSrc()
public String getScheme()
public Set<String> getSchemes()
public String getUser()
You can use the class PAMCredentials to create a set of PAM credentials for authentication. The supported constructor is public PAMCredentials(String pass).
Most RAD objects that are represented in the ADR document as <interfaces>. You can search RAD objects by searching the RAD namespace. To access a RAD object, you need a proxy, which is used to search the RAD namespace. An interface proxy class enables you to use a proxy to search the RAD namespace. The interface proxy is defined in the binding module of each interface.
The proxy provides the base name and the version details for the interface instances and is structured as follows:
<domain name>:type=<interface name>[,optional additional key value pairs]
The <domain name> and the <interface name> are automatically derived from the ADR IDL definition and are stored in the module binding.
Certain interfaces return or accept object references directly to or from clients. These objects might not be named. Objects that are not named are anonymous. Anonymous objects cannot be looked up in the RAD namespace, but the interface provides access methods that make it simple to interact with them.
The names are changed to be represented by a domain string and a Map <String, String> for the key or value pairs. The ADRName constructors are expanded to include:
ADRName(String domain, Map<String, String> kvpairs) ADRName(String domain, Map<String, String> kvpairs, ProxyInterface proxy, Version version)
Using the Connection class, you can list the objects by name and obtain a remote object reference.
A module developer creates a singleton to represent an interface. This interface can be accessed easily. For example, the zonemgr module defines a singleton interface, ZoneInfo. It contains information about the zone that contains the RAD instance with which you are communicating.
In Java, you need to compile the code with the language binding in the CLASSPATH. RAD Java Language bindings are in the system/management/rad/client/rad-java package.
The JAR files for the various bindings are installed in /usr/lib/rad/java. Each major interface version is accessible in a JAR file which is named after the source ADR document and it's major version number. For example, to access major version 1 of the zonemgr API, use /usr/lib/rad/java/zonemgr_1.jar. Symbolic links are provided as an indication of the default version a client should use.
Example 17 Java Language – Obtaining Reference to a RAD Singletonimport com.oracle.solaris.rad.connect.Connection; import com.oracle.solaris.rad.zonemgr.ZoneInfo; Connection con = Connection.connectUnix(); System.out.println("Connected: " + con.toString()); ZoneInfo zi = con.getObject(new ZoneInfo()); System.out.println("ZoneInfo: " + zi.getname());
In this example, you have performed the following:
Imported ZoneInfo and Connection from the zonemgr binding and the rad.connect package
Connected to the local RAD instance
Obtained a remote object reference directly by using a proxy instance
After you have the remote reference, you can access the properties and the methods directly. In the RAD Java implementation, all properties are accessed using the getter or setter syntax. Thus, you invoke getname() to access the name property.
An interface can contain multiple RAD instances. For example, the zonemgr module defines a Zone interface and there is an instance for each zone on the system. The Connection class provides the list_objects() method to list the interface instances as shown in the following example.
Example 18 Java Language – Listing RAD Interface Instancesimport com.oracle.solaris.rad.client.ADRName; import com.oracle.solaris.rad.connect.Connection; import com.oracle.solaris.rad.zonemgr.Zone; Connection con = Connection.connectUnix(); System.out.println("Connected: " + con.toString()); for (ADRName name: con.listObjects(new Zone())) { System.out.println("ADR Name: " + name.toString()); }
A list of names (ADRName is the class name) are returned by the list_objects() method from the Connection class. After you have a name, you can obtain a remote object reference easily as shown in the following example.
Example 19 Java Language – Obtaining a Remote Object Reference From a RAD Nameimport com.oracle.solaris.rad.client.ADRName; import com.oracle.solaris.rad.connect.Connection; import com.oracle.solaris.rad.zonemgr.Zone; Connection con = Connection.connectUnix(); System.out.println("Connected: " + con.toString()); for (ADRName name: con.listObjects(new Zone())) { Zone zone = con.getObject(name); System.out.println("Name: " + zone.getname()); }
You can search for a zone by its name or ID or a set of zones by pattern matching. You can extend the definition of a name provided by a proxy. For example, if zones are uniquely identified by a key name, then you can find a zone with name test-0 as shown in the following example. This example uses glob patterns to find a zone.
Example 20 Java Language – Using Glob Patterns in RADimport com.oracle.solaris.rad.client.ADRName; import com.oracle.solaris.rad.client.ADRGlobPattern; import com.oracle.solaris.rad.connect.Connection; import com.oracle.solaris.rad.zonemgr.Zone; Connection con = Connection.connectUnix(); System.out.println("Connected: " + con.toString()); String keys[] = { "name" }; String values[] = { "test-0" }; ADRGlobPattern pat = new ADRGlobPattern(keys, values); for (ADRName name: con.listObjects(new Zone(), pat)) { System.out.println("ADR Name: " + name.toString()); }
In this example, the ADRGlobPattern class (imported from the com.oracle.solaris.rad.client package) is used to refine the search. The list_objects() method from the Connection class is used, but the search is refined by extending the name definition. The ADRGlobPattern class takes an array of keys and an array of values and extends the name used in the search.
You can use a glob pattern to find zones with wildcard pattern matching. Keys or Values in the pattern may contain *, which is interpreted as wildcard pattern matching. For example, you can find all zones with a name which begins with test as follows.
Example 21 Java Language – Using Glob Patterns With Wildcardsimport com.oracle.solaris.rad.client.ADRName; import com.oracle.solaris.rad.client.ADRGlobPattern; import com.oracle.solaris.rad.connect.Connection; import com.oracle.solaris.rad.zonemgr.Zone; Connection con = Connection.connectUnix(); System.out.println("Connected: " + con.toString()); String keys[] = { "name" }; String values[] = { "test*" }; ADRGlobPattern pat = new ADRGlobPattern(keys, values); for (ADRName name: con.listObjects(new Zone(), pat)) { System.out.println("ADR Name: " + name.toString()); }
It can be simpler to use Map rather than arrays of keys and values. This example uses a map of keys and values rather than arrays of keys and values.
Example 22 Java Language – Using Maps With Patternsimport com.oracle.solaris.rad.client.ADRName; import com.oracle.solaris.rad.client.ADRGlobPattern; import com.oracle.solaris.rad.connect.Connection; import com.oracle.solaris.rad.zonemgr.Zone; Connection con = Connection.connectUnix(); System.out.println("Connected: " + con.toString()); Map<String, String> kvpairs = new HashMap<String, String>(); kvpairs.put("name", "test*"); ADRGlobPattern pat = new ADRGlobPattern(kvpairs); for (ADRName name: con.listObjects(new Zone(), pat)) { System.out.println("ADR Name: " + name.toString()); }
You can also use RAD's ERE search capabilities to search a zone. For example, you can find only zones with the name test-0 or test-1 as shown in the following example.
Example 23 Java Language – Using Regex Patternsimport com.oracle.solaris.rad.client.ADRName; import com.oracle.solaris.rad.client.ADRRegexPattern; import com.oracle.solaris.rad.connect.Connection; import com.oracle.solaris.rad.zonemgr.Zone; Connection con = Connection.connectUnix(); System.out.println("Connected: " + con.toString()); String keys[] = { "name" }; String values[] = { "test-0|test-1" }; ADRRegexPattern pat = new ADRRegexPattern(keys, values); for (ADRName name: con.listObjects(new Zone(), pat)) { System.out.println("ADR Name: " + name.toString()); }
The key and the value must be valid ERE as determined by the instance of RAD to that you are connected. The expression is compiled and executed on the server.
An API is defined by a module developer. It contains one or more of the following components, each of which performs a task:
Enumerations
Values
Structures
Fields
Dictionary
Interfaces
Properties
Methods
Events
These components are defined in an ADR IDL document. The radadrgen utility is used to process the document to generate language specific components which facilitates client-server interactions within RAD. For more information about the role of ADR and RAD, see Abstract Data Representation. Brief descriptions of each component follows.
Enumerations provide a restricted range of choices for a property, an interface method parameter, result, or error.
To access an enumerated type, import the generated class and interact with the enumeration.
Example 24 Java Language – Using RAD Enumerationsimport com.oracle.solaris.rad.zonemgr.ErrorCode; System.out.println(ErrorCode.NONE); System.out.println(ErrorCode.COMMAND_ERROR);
Structs are used to define new types and are composed from existing built-in types and other user defined types. Structs are simple forms of interfaces with no methods or events. They are not included in the RAD namespace.
The zonemgr module defines a Property struct, which represents an individual zone configuration property. The structure has the following members name, type, value, listValue, and complexValue. Like enumerations, structs can be interacted directly once the binding is imported.
Example 25 Java Language – Using RAD Structsimport com.oracle.solaris.rad.zonemgr.Property; Property prop = new Property(); prop.setName("my name"); prop.setValue("a value"); System.out.println(prop.getName()); System.out.println(prop.getValue());
To support the dictionary type, Java client uses the java.util.Map<K,V> interface. For more information about dictionary, see Dictionary Definitions.
The following example shows how to read and write a property defined in Example 49, Defining a Dictionary.
//reading a property value Map<Integer, String> property = o.getDictProp(); //writing a property value Map<Integer, String> property = new HashMap<Integer, String>(); .... o.setDictProp(property);
Interfaces, also known as objects, are the entities, which populate the RAD namespace. They must have a name. An interface is composed of events, properties, and methods.
For more information, see RAD Namespace in Java.
Once you have an object reference, you can use this object reference to interact with RAD directly. All attributes and methods defined in the IDL are accessible directly as attributes and methods of the Java objects that are returned by the getObject() function. The attributes are accessed using the automatically generated getter or setter. For example, if the property is name, you would use getname or setname(<value>). In this example, you get a reference to a zone and then boot the zone.
Example 26 Java Language – Invoking a RAD Remote Methodimport com.oracle.solaris.rad.client.ADRName; import com.oracle.solaris.rad.client.ADRGlobPattern; import com.oracle.solaris.rad.connect.Connection; import com.oracle.solaris.rad.zonemgr.Zone; Connection con = Connection.connectUnix(); System.out.println("Connected: " + con.toString()); String keys[] = { "name" }; String values[] = { "test-0" }; ADRGlobPattern pat = new ADRGlobPattern(keys, values); for (ADRName name: con.listObjects(new Zone(), pat)) { Zone z = (Zone) con.getObject(name); z.boot(null); }
In this example, you have connected to the RAD instance, created a search for a specific object, retrieved a reference to the object, and invoked a remote method on the object.
Accessing a remote property is similar to using a remote method.
Example 27 Java Language – Accessing a RAD Remote Propertyimport com.oracle.solaris.rad.client.ADRName; import com.oracle.solaris.rad.client.ADRGlobPattern; import com.oracle.solaris.rad.connect.Connection; import com.oracle.solaris.rad.zonemgr.*; Connection con = Connection.connectUnix(); System.out.println("Connected: " + con.toString()); String keys[] = { "name" }; String values[] = { "test-0" }; ADRGlobPattern pat = new ADRGlobPattern(keys, values); for (ADRName name: con.listObjects(new Zone(), pat)) { Zone z = (Zone) con.getObject(name); Resource filter = new Resource("global", null, null); List<Property> props = z.getResourceProperties(filter, null); System.out.println("Properties:"); for (Property prop: props) { System.out.printf("\t%s = %s\n",prop.getName(), prop.getValue()); } }
In this example, you have accessed the list of global resource properties of the Zone and printed the name and value of every Property.
This example shows how to subscribe and handle events. The ZoneManager instance defines a stateChange event, which clients can subscribe for information about changes in the runtime state of a zone.
Example 28 Java Language – Subscribing to and Handling RAD Eventsimport com.oracle.solaris.rad.client.ADRName; import com.oracle.solaris.rad.client.RadEvent; import com.oracle.solaris.rad.client.RadEventHandler; import com.oracle.solaris.rad.connect.Connection; import com.oracle.solaris.rad.zonemgr.*; ZoneManager zmgr = con.getObject(new ZoneManager()); con.subscribe(zmgr, "statechange", new StateChangeHandler()); Thread.currentThread().sleep(100000000); class StateChangeHandler extends RadEventHandler { public void handleEvent(RadEvent event, Object payload) { StateChange obj = (StateChange) payload; System.out.printf("Event: %s", event.toString()); System.out.printf("\tcode: %s\n", obj.getZone()); System.out.printf("\told: %s\n", obj.getOldstate()); System.out.printf("\tnew: %s\n", obj.getNewstate()); } }
To handle an event, implement the RadEventInterface class. The com.oracle.solaris.rad.client package provides a default implementation (RadEventHandler) with limited functions. This class can be extended to provide additional event handling logic as in the example above.
In this example, you have subscribed to a single event by passing a handler and a reference to the ZoneManager object. The handler is invoked asynchronously by the framework with various event details and provided the user data.
Java provides a exception handling mechanism and RAD errors are propagated using this method. RAD delivers a variety of errors, but the error that requires handling is RadObjectException. The following example shows how to handle RAD errors.
Example 29 Java Language – Handling RAD Errors<imports..> Connection con = Connection.connectUnix(); for (ADRName name: con.listObjects(new Zone())) { Zone zone = con.getObject(name); try { zone.boot(null); }catch (RadObjectException oe) { Result res = (Result) oe.getPayload(); System.out.println(res.getCode()); if (res.getStdout() != null) System.out.println(res.getStdout()); if (res.getStderr() != null) System.out.println(res.getStderr()); } }