JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Remote Administration Daemon Developer Guide     Oracle Solaris 11.1 Information Library
search filter icon
search icon

Document Information

Preface

1.  Introduction

2.  Concepts

3.  Abstract Data Representation

4.  libadr

5.  Client Libraries

Java/JMX Client

Connecting to the rad Server

RadConnector.PROTOCOL_UNIX

RadConnector.PROTOCOL_TCP

RadConnector.PROTOCOL_TLS

RadConnector.PROTOCOL_PRIVATE

RadConnector.PROTOCOL_ZONESBRIDGE

radadrgen Usage

Enums

Structured Types

Unions

Interfaces

Caveats

Python Client

Modules

client

util

6.  Module Development

7.  rad Best Practices

A.  rad Binary Protocol

Java/JMX Client

Connecting to the rad Server

Connections to a rad server in Java are made through JMX. A JMX connection is established with the following:

Several protocols for connecting to a rad server are supported and are defined in the com.oracle.solaris.rad.jmx class. Unless explicitly mentioned, a host, port, path, or options is not applicable.

These protocols are:

RadConnector.PROTOCOL_UNIX

A local UNIX domain socket connection. The path is the fully qualified name of the socket.

Example 5-1 RadConnector.PROTOCOL_UNIX

JMXServiceURL url = new JMXServiceURL(RadConnector.PROTOCOL_UNIX,
  "", 0, "/system/volatile/rad/radsocket");
JMXConnector connector = JMXConnectorFactory.connect(url);

RadConnector.PROTOCOL_TCP

A local/remote TCP connection. A host and/or port may be specified.

Example 5-2 RadConnector.PROTOCOL_TCP

JMXServiceURL url = new JMXServiceURL(RadConnector.PROTOCOL_TCP,
    "myhost", 0);
JMXConnector connector = JMXConnectorFactory.connect(url);

RadConnector.PROTOCOL_TLS

A local/remote TLS connection. A host and/or port may be specified.

Expected parameters:

RadConnector.KEY_TLS_TRUSTSTORE (required)

The full path to a local rad truststore file

RadConnector.KEY_TLS_TRUSTPASS (required)

The password for the local rad truststore

RadConnector.KEY_TLS_RADMANAGER (required)

An instance of com.oracle.solaris.rad.RadTrustManager for key management

Example 5-3 RadConnector.PROTOCOL_TLS

Map<String, Object> env = new HashMap<String, Object>();
env.put(RadConnector.KEY_TLS_TRUSTSTORE, "/etc/myapp/truststore");
env.put(RadConnector.KEY_TLS_TRUSTPASS, "trustpass");

JMXServiceURL url = new JMXServiceURL(
    RadConnector.PROTOCOL_TLS, host, 0);

JMXConnector connector = JMXConnectorFactory.newJMXConnector(url, null);

for (;;) {
    RadTrustManager mtm = new RadTrustManager();
    env.put(RadConnector.KEY_TLS_RADMANAGER, mtm);

    try {
        connector.connect(env);
        break;
    } catch (IOException e) {
        X509Certificate[] chain = mtm.getBadChain();
        if (chain == null) {
            throw e;
        }
    }
}

RadConnector.PROTOCOL_PRIVATE

A local connection to a rad instance private to this process, spawned when the connection is established. The resulting rad communicates through its stdin/stdout.

Expected parameters:

RadConnector.PRIVATE_ROOT (String, optional)

A full path to prefix the to each relatively named module in the RadConnector.PRIVATE_MODULES parameter, if specified

RadConnector.PRIVATE_MODULES (String[], optional)

A list of modules to load, as with /usr/lib/rad/rad -M module

RadConnector.PRIVATE_AUXARGS (String[], optional)

Additional arguments to pass to the spawned rad instance

Example 5-4 RadConnector.PROTOCOL_PRIVATE

Map<String, Object> env = new HashMap<String, Object>();
String[] auxargs = { "-d", "-e", "30" };
String[] modules = { "mod_usermgmt.so", "mod_nameservice.so" };

env.put(RadConnector.PRIVATE_AUXARGS, auxargs);
env.put(RadConnector.PRIVATE_MODULES, modules);
env.put(RadConnector.PRIVATE_ROOT, "/usr/share/modules");

JMXServiceURL url = new JMXServiceURL(
    RadConnector.PROTOCOL_PRIVATE, "", 0);

JMXConnector connector = JMXConnectorFactory.newJMXConnector(url, env);

RadConnector.PROTOCOL_ZONESBRIDGE

A connection to a non-global zone's local UNIX rad instance, through an existing local or remote rad connection to its global zone. The name of the non-global zone is specified as the host. The non-global zone user is specified as the path.

Expected parameters:

RadConnector.KEY_ZONESBRIDGE_MXBEAN (com.oracle.solaris.rad.zonesbridge.IOMXBean, required)

An IOMXBean from an existing rad connection to the global zone, retrieved with a domain "com.oracle.solaris.rad.zonesbridge" and a "type=IO" key/value pair.

Example 5-5 RadConnector.PROTOCOL_ZONESBRIDGE

// Create a connection to some host
MBeanServerConnection mbsc = ...

ObjectName zioName = new ObjectName(
  "com.oracle.solaris.rad.zonesbridge", "type", "IO");
IOMXBean zio = JMX.newMXBeanProxy(mbsc, zioName, IOMXBean.class);

// The zone to connect to
String zone = "nerd-vpn";

// The non-global-zone user, or "" to connect as root
String zoneUser = "talley";

// Create a connection to the non-global zone on the connected host
JMXServiceURL zUrl = new JMXServiceURL(
    RadConnector.PROTOCOL_ZONESBRIDGE, zone, 0, "/" + zoneUser);

Map<String, Object> env = new HashMap<String, Object>();
env.put(RadConnector.KEY_ZONESBRIDGE_MXBEAN, zio);

JMXConnector connector = JMXConnectorFactory.connect(zUrl, env);

radadrgen Usage

In the Java/JMX environment, elements declared in the module specification are translated to Java classes and interfaces. The tool that does this translation is /usr/bin/radadrgen:

/usr/bin/radadrgen [ -N ] -j dir [ -i ] spec.xml

The Java classes and interfaces generated by radadrgen are as follows, where package is determined from the <api> name or a supplied pragma:

Element
radadrgen-Generated Class
Description
<interface>
package.interfaceMXBean
MXBean interface, implemented by object returned by the rad server
<struct>
package.struct
struct interface
package.structImpl
struct implementation (if -i is used)
<union>
package.union
union interface
package.unionImpl
union implementation
<enum>
package.enum
enum class

See the section on object naming for details.

Enums

For example, suppose you have the rad module specification example.xml:

<api xmlns="http://xmlns.oracle.com/radadr"
  name="com.example.foo">

  <enum name="Color">
    <value name="Red" />
    <value name="Green" />
    <value name="Blue" />
  </enum>
  ...
</api>

Calling /usr/bin/radadrgen -j dir example.xml generates a native Java enum class:

package com.example.foo;

public enum Color {
    Red,
    Green,
    Blue,
}

Structured Types

Adding a <struct> to the module API produces a Java interface that models the structured type. For example:

<struct name="Person">
  <field type="string" name="name" />
  <field type="integer" name="age" />
  <field typeref="Color" name="favoriteColor" />
</struct>

resulting Java interface:

package com.example.foo;

public interface Person {
    String getName();
    int getAge();
    Color getFavoriteColor();
}

If the -i is also passed to radadrgen, an implementation of the Person interface is also generated:

package com.example.foo;

public class PersonImpl implements Person {
    private String name_;
    private int age_;
    private Color favoriteColor_;

    public PersonImpl() {
    }

    public PersonImpl(String name, int age, Color favoriteColor) {
        name_ = name;
        age_ = age;
        favoriteColor_ = favoriteColor;
    }

    public String getName() {
        return name_;
    }

    public int getAge() {
        return age_;
    }

    public Color getFavoriteColor() {
        return favoriteColor_;
    }

    public void setName(String arg) {
        name_ = arg;
    }

    public void setAge(int arg) {
        age_ = arg;
    }

    public void setFavoriteColor(Color arg) {
        favoriteColor_ = arg;
    }
}

This process can be useful in client code to quickly create and use a basic object that implements a structured type's interface.

Unions

When adding a discriminated union to a module API, radadrgen produces a Java interface that models the union. For example:

Discriminated Union:

<union name="ColorData" typeref="Color">
  <arm value="Red" type="string" />
  <arm value="Green" type="integer" />
  <arm value="Blue" type="float" />
</union>

Resulting Java interface:

package com.example.foo;

public interface ColorData {
    Color getArm();

    String getData_Red();
    Integer getData_Green();
    Float getData_Blue();
    ...
}

To use a union, the getArm() method is first called to determine which of the union arms is active. Based on the return value of that method, the appropriate getData_*() method can be called to get the data encapsulated in the union.

To create a union, the generated Java interface also includes several static convenience classes, as shown in the following example.

public interface ColorData {
    ...

    static class arm_Red extends ColorDataImpl {
        private String armdata_;
        public arm_Red(String armdata) {
            super(Color.Red);
            armdata_ = armdata;
        }
        @Override
        public String getData_Red() { return armdata_; }
    }

    static class arm_Green extends ColorDataImpl {
        ...
    }

    static class arm_Blue extends ColorDataImpl {
        ...
    }
}

These inner classes provide a quick way to quickly create and use a basic object that implements the generated union interface for a given union arm.

Interfaces

Interfaces are the reason that modules exist. For an <interface> added to a module, radadrgen produces a Java MXBean interface. For example:

Interface:

<interface name="Population">
  <property name="groupName" access="rw" type="string"/>
  <property name="people" access="ro">
    <list typeref="Person" />
  </property>
  <method name="add">
    <argument typeref="Person" name="person" />
  </method>
</interface>

Resulting Java MXBean interface:

package com.example.foo;

public interface PopulationMXBean {
    String getgroupName();

    void setgroupName(String groupName);

    java.util.List<Person> getpeople();

    void add(Person person);
}

This MXBean is implemented by the objects returned by the rad server:

// Retrieve the Population object
ObjectName oName = new ObjectName("com.example.foo",
    "type", "Population");
PopulationMXBean pop = JMX.newMXBeanProxy(mbsc,
    oName, PopulationMXBean.class);

// Access a property
List<Person> people = pop.getpeople();

// Call a method
pop.add(new PersonImpl("talley", Color.GREEN));

Caveats

Note the following cautions:


Caution

Caution - To eliminate the ambiguity inherent to the JMX ObjectName quoting rules, all key values returned by interfaces that return ObjectNames are quoted by the JMX client connector before being passed to the caller. For compatibility, the JMX client connector will accept object names with unquoted key values.