Go to main content

Remote Administration Daemon Developer's Guide

Exit Print View

Updated: April 2020
 
 

Java Language Environment in RAD

    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


Note -  Most of the examples are based on the zonemgr interface. To better understand these examples, see zonemgr ADR Interface Description Language Example for this module to assist in your understanding of the examples.

Connecting to RAD in Java

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.

Connecting to a RAD Local Instance in Java

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 Connection
import com.oracle.solaris.rad.connect.Connection;

Connection con = Connection.connectUnix();

Connecting to a Remote RAD Instance and Authenticating in Java

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 7777
import 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();

Connecting to a RAD Instance by Using a URI in Java

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).

RAD Namespace in Java

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.

Creating a Name for a RAD Object in Java

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)

Searching for RAD Objects in Java

Using the Connection class, you can list the objects by name and obtain a remote object reference.

RAD Singletons in Java

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 Singleton
import 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.

Listing RAD Interface Instances in Java

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 Instances
import 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());
}

Remote Object References and RAD Names in Java

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 Name
import 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());
}

Sophisticated RAD Searches in Java

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 RAD
import 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.

Glob Pattern Searching in RAD in Java

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 Wildcards
import 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());
}
Using Maps When Pattern Searching in RAD in Java

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 Patterns
import 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());
}
Regex Pattern Searching in RAD in Java

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 Patterns
import 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.

Interface Components for RAD in Java

    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.

RAD Property Enumerations in Java

Enumerations provide a restricted range of choices for a property, an interface method parameter, result, or error.

Using RAD Enumeration Types in Java

To access an enumerated type, import the generated class and interact with the enumeration.

Example 24  Java Language – Using RAD Enumerations
import com.oracle.solaris.rad.zonemgr.ErrorCode;

System.out.println(ErrorCode.NONE);
System.out.println(ErrorCode.COMMAND_ERROR);

RAD Structs in Java

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.

Using RAD Struct Types in Java

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 Structs
import 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());

Dictionary Support for RAD in Java

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);

RAD Interfaces in Java

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.

Obtaining a RAD Object Reference in Java

For more information, see RAD Namespace in Java.

Working With RAD Object References 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 Method
import 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.

RAD Remote Property Example in Java

Accessing a remote property is similar to using a remote method.

Example 27  Java Language – Accessing a RAD Remote Property
import 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.

RAD Event Handling

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 Events
import 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 Error Handling in RAD

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());
       }
}

Note -  With RadException exceptions, you might get a payload. This payload is only present if your interface method or property has defined an error element, where the payload is the content of that error. If the interface method or property defines no error element for the interface method or property, then no payload exists and error has a value of null.