Package org.acplt.oncrpc

## Class OncRpcClient

- java.lang.Object
- - org.acplt.oncrpc.OncRpcClient

- Direct Known Subclasses:
    `OncRpcHttpClient`, `OncRpcTcpClient`, `OncRpcUdpClient`

      public abstract class OncRpcClient
      extends java.lang.Object

  The abstract `OncRpcClient` class is the foundation for protcol-specific ONC/RPC clients. It encapsulates protocol-independent functionality, like port resolving, if no port was specified for the ONC/RPC server to contact. This class also provides the method skeleton, for instance for executing procedure calls.

  In order to communicate with an ONC/RPC server, you need to create an ONC/RPC client, represented by classes derived from `OncRpcClient`. The most generic way to generate an ONC/RPC client is as follows: use `newOncRpcClient(...)` and specify:

  - the host (of class InetAddress) where the ONC/RPC server resides,
  - the ONC/RPC program number of the server to contact,
  - the program's version number,
  - and finally the IP protocol to use when talking to the server. This can be either `OncRpcProtocols.ONCRPC_UDP` or `OncRpcProtocols.ONCRPC_TCP`.

  The next code snippet shows how to create an ONC/RPC client, which can communicate over UDP/IP with the ONC/RPC server for program number `0x49678` on the same host (by coincidence, this is the program number of the ACPLT/KS protocol).

       OncRpcClient client;
       try {
           client = OncRpcClient.newOncRpcClient(
               InetAddress.getByName("localhost"),
               0x49678, 1,
               OncRpcProtocols.ONCRPC_UDP);
       } catch ( OncRpcProgramNotRegisteredException e ) {
           System.out.println("ONC/RPC program server not found");
           System.exit(0);
       } catch ( OncRpcException e ) {
           System.out.println("Could not contact portmapper:");
           e.printStackTrace(System.out);
           System.exit(0);
       } catch ( IOException e ) {
           System.out.println("Could not contact portmapper:");
           e.printStackTrace(System.out);
           System.exit(0);
       }

  This code snippet also shows exception handling. The most common error you'll see is probably an `OncRpcProgramNotRegisteredException`, in case no such program number is currently registered at the specified host. An `OncRpcProgramNotRegisteredException` is a subclass of `OncRpcException` with a detail of `OncRpcException.RPC_PROGNOTREGISTERED`. In case no ONC/RPC portmapper is available at the specified host, you'll get an `OncRpcTimeoutException` instead (which is again a subclass of `OncRpcException` with a detail of `OncRpcException.RPC_TIMEDOUT`). You might also get an IOException when using TCP/IP and the server can not be contacted because it does not accept new connections.

  Instead of calling `OncRpcClient.newOncRpcClient(...)` you can also directly create objects of classes `OncRpcTcpClient` and `OncRpcUdpClient` if you know at compile time which kind of IP protocol you will use.

  With a client proxy in your hands, you can now issue ONC/RPC calls. As a really, really simple example -- did I say "simple example"? -- we start with the famous ONC/RPC ping call. This call sends no parameters and expects no return from an ONC/RPC server. It is just used to check whether a server is still responsive.

       System.out.print("pinging server: ");
       try {
           client.call(0, XdrVoid.XDR_VOID, XdrVoid.XDR_VOID);
       } catch ( OncRpcException e ) {
           System.out.println("method call failed unexpectedly:");
           e.printStackTrace(System.out);
           System.exit(1);
       }
       System.out.println("server is alive.");

  By definition, the ONC/RPC ping call has program number 0 and expects no parameters and replies with no result. Thus we just specify an empty parameter and result in the form of the static `XdrVoid.XDR_VOID` object, when calling the ping procedure in the server using the `call(...)` method.

  For more complex and sometimes more useful ONC/RPC calls, you will need to write appropriate ONC/RPC parameter and reply classes. Unfortunately, at this time there's no compiler available to compile `.x` files into appropriate Java classes. Well -- surely a lot of people will now associate completely wrong things with "x files", but in our case there's no new age or whatever mumbo jumbo involved, but definitions of XDR data structures instead. For the next example, let's pretend our server provides the answer to all questions when called with procedure number 42. Let's also pretend that this ONC/RPC call expects a question in form of a string and returns the answer as an integer. So we need to define two classes, one for the call's parameters and one for the reply. But let us first examine the class containing a call's parameters:

       class Parameters implements XdrAble {
           public String question;

           public void xdrEncode(XdrEncodingStream xdr)
               throws OncRpcException, IOException {
               xdr.xdrEncodeString(question);
           }
           public void xdrDecode(XdrDecodingStream xdr)
               throws OncRpcException, IOException {
               question = xdr.xdrDecodeString();
           }
       }

  The `Parameters` class implements `XdrAble`, so instances of it can be sent and received over the network using Sun's XDR protocol. What exactly is sent over the wire is up to the two methods `xdrEncode(...)` and `xdrDecode(...)`. The `xdrEncode` method is responsible to "encode" the data to be sent over the network. On the other side, `xdrDecode` is responsible to restore an object's state from the data received over the network. In our example, these methods either send or receive a string.

  The class defining the reply of our the-answer-to-all-questions ONC/RPC call is now straightforward:

       class Answer implements XdrAble {
           public int definitiveAnswer;

           public void xdrEncode(XdrEncodingStream xdr)
               throws OncRpcException, IOException {
               xdr.xdrEncodeInt(definitiveAnswer);
           }
           public void xdrDecode(XdrDecodingStream xdr)
               throws OncRpcException, IOException {
               definitiveAnswer = xdr.xdrDecodeInt();
           }
       }

  Finally, to ask a question, you need to create the parameter object and fill it with the parameters to be sent. Then create the object later receiving the reply. Finally issue the ONC/RPC call:

       Parameters parameters = new Parameters();
       parameters.question = "What is the final answer to all our questions?";

       Answer answer = new Answer();

       try {
           client.call(42, parameters, answer);
       } catch ( OncRpcException e ) {
       } catch ( IOException e ) {
       }
       System.out.println(parameters.question);
       System.out.println("And the answer is: " + answer.definitiveAnswer);

  When you do not need the client proxy object any longer, you should return the resources it occupies to the system. Use the `close()` method for this.

       client.close();
       client = null; // Hint to the garbage (wo)man

  `Authentication` can be done as follows: just create an authentication object and hand it over to the ONC/RPC client object.

       OncRpcClientAuth auth = new OncRpcClientAuthUnix(
                                       "marvin@ford.prefect",
                                       42, 1001, new int[0]);
       client.setAuth(auth);

  The `authentication `AUTH_UNIX`` will handle shorthand credentials (of type `AUTH_SHORT`) transparently. If you do not set any authentication object after creating an ONC/RPC client object, `AUTH_NONE` is used automatically.

  TCP-based ONC/RPC clients also support call batching (exception handling ommited for clarity):

       OncRpcTcpClient client = new OncRpcTcpClient(
           InetAddress.getByName("localhost"),
           myprogramnumber, myprogramversion,
           OncRpcProtocols.ONCRPC_TCP);
       client.callBatch(42, myparams, false);
       client.callBatch(42, myotherparams, false);
       client.callBatch(42, myfinalparams, true);

  In the example above, three calls are batched in a row and only be sent all together with the third call. Note that batched calls must not expect replies, with the only exception being the last call in a batch:

       client.callBatch(42, myparams, false);
       client.callBatch(42, myotherparams, false);
       client.call(43, myfinalparams, myfinalresult);

  Version:
    $Revision: 1.3 $ $Date: 2003/08/14 13:48:33 $ $State: Exp $ $Locker: $
  Author:
    Harald Albrecht
  See Also:
    `OncRpcPortmapClient`, `OncRpcTcpClient`, `OncRpcUdpClient`, `OncRpcClientAuth`

- - ### Field Summary

    Fields
    Modifier and Type | Field | Description
    --- | --- | ---
    `protected OncRpcClientAuth` | `auth` | Authentication protocol object to be used when issuing ONC/RPC calls.
    `protected java.net.InetAddress` | `host` | Internet address of the host where the ONC/RPC server we want to communicate with is located at.
    `protected int` | `port` | Port number at which the ONC/RPC server can be contacted.
    `protected int` | `program` | Program number of the ONC/RPC server to communicate with.
    `protected int` | `timeout` | Timeout (in milliseconds) for communication with an ONC/RPC server.
    `protected int` | `version` | Version number of the ONC/RPC server to communicate with.
    `protected int` | `xid` | The message id (also sometimes known as "transaction id") used for the next call message.

  - ### Constructor Summary

    Constructors
    Modifier | Constructor | Description
    --- | --- | ---
    `protected` | `OncRpcClient​(java.net.InetAddress host, int program, int version, int port, int protocol)` | Constructs an `OncRpcClient` object (the generic part).

  - ### Method Summary

    All Methods Static Methods Instance Methods Abstract Methods Concrete Methods
    Modifier and Type | Method | Description
    --- | --- | ---
    `abstract void` | `call​(int procedureNumber, int versionNumber, XdrAble parameters, XdrAble result)` | Calls a remote procedure on an ONC/RPC server.
    `void` | `call​(int procedureNumber, XdrAble params, XdrAble result)` | Calls a remote procedure on an ONC/RPC server.
    `void` | `close()` | Close the connection to an ONC/RPC server and free all network-related resources.
    `OncRpcClientAuth` | `getAuth()` | Returns the current authentication.
    `abstract java.lang.String` | `getCharacterEncoding()` | Get the character encoding for (de-)serializing strings.
    `java.net.InetAddress` | `getHost()` | Returns the IP address of the server's host this client is connected to.
    `int` | `getPort()` | Returns port number of the server this client is connected to.
    `int` | `getProgram()` | Returns the program number specified when creating this client.
    `int` | `getTimeout()` | Retrieve the current timeout set for remote procedure calls.
    `int` | `getVersion()` | Returns the version number specified when creating this client.
    `static OncRpcClient` | `newOncRpcClient​(java.net.InetAddress host, int program, int version, int protocol)` | Creates a new ONC/RPC client object, which can handle the requested `protocol`.
    `static OncRpcClient` | `newOncRpcClient​(java.net.InetAddress host, int program, int version, int port, int protocol)` | Creates a new ONC/RPC client object, which can handle the requested `protocol`.
    `protected void` | `nextXid()` | Create next message identifier.
    `void` | `setAuth​(OncRpcClientAuth auth)` | Sets the authentication to be used when making ONC/RPC calls.
    `abstract void` | `setCharacterEncoding​(java.lang.String characterEncoding)` | Set the character encoding for (de-)serializing strings.
    `void` | `setTimeout​(int milliseconds)` | Set the timout for remote procedure calls to wait for an answer from the ONC/RPC server.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### host

          protected java.net.InetAddress host

      Internet address of the host where the ONC/RPC server we want to communicate with is located at.

    - #### timeout

          protected int timeout

      Timeout (in milliseconds) for communication with an ONC/RPC server. ONC/RPC calls through the `call(int, XdrAble, XdrAble)` method will throw an exception if no answer from the ONC/RPC server is received within the timeout time span.

    - #### program

          protected int program

      Program number of the ONC/RPC server to communicate with.

    - #### version

          protected int version

      Version number of the ONC/RPC server to communicate with.

    - #### port

          protected int port

      Port number at which the ONC/RPC server can be contacted.

    - #### xid

          protected int xid

      The message id (also sometimes known as "transaction id") used for the next call message.

    - #### auth

          protected OncRpcClientAuth auth

      Authentication protocol object to be used when issuing ONC/RPC calls.

  - ### Constructor Detail

    - #### OncRpcClient

          protected OncRpcClient​(java.net.InetAddress host,
                                 int program,
                                 int version,
                                 int port,
                                 int protocol)
                          throws OncRpcException,
                                 java.io.IOException

      Constructs an `OncRpcClient` object (the generic part). If no port number is given (that is, `port` is `0`), then a port lookup using the portmapper at `host` is done.
      Parameters:
        `host` - Host address where the desired ONC/RPC server resides.
        `program` - Program number of the desired ONC/RPC server.
        `version` - Version number of the desired ONC/RPC server.
        `protocol` - `Protocol` to be used for ONC/RPC calls. This information is necessary, so port lookups through the portmapper can be done.
      Throws:
        `OncRpcException` - if an ONC/RPC error occurs.
        `java.io.IOException` - if an I/O error occurs.

  - ### Method Detail

    - #### newOncRpcClient

          public static OncRpcClient newOncRpcClient​(java.net.InetAddress host,
                                                     int program,
                                                     int version,
                                                     int protocol)
                                              throws OncRpcException,
                                                     java.io.IOException

      Creates a new ONC/RPC client object, which can handle the requested `protocol`.
      Parameters:
        `host` - Host address where the desired ONC/RPC server resides.
        `program` - Program number of the desired ONC/RPC server.
        `version` - Version number of the desired ONC/RPC server.
        `protocol` - `Protocol` to be used for ONC/RPC calls.
      Throws:
        `OncRpcException` - if an ONC/RPC error occurs.
        `java.io.IOException` - if an I/O error occurs.

    - #### newOncRpcClient

          public static OncRpcClient newOncRpcClient​(java.net.InetAddress host,
                                                     int program,
                                                     int version,
                                                     int port,
                                                     int protocol)
                                              throws OncRpcException,
                                                     java.io.IOException

      Creates a new ONC/RPC client object, which can handle the requested `protocol`.
      Parameters:
        `host` - Host address where the desired ONC/RPC server resides.
        `program` - Program number of the desired ONC/RPC server.
        `version` - Version number of the desired ONC/RPC server.
        `port` - Port number of the ONC/RPC server. Specifiy `0` if this is not known and the portmap process located at host should be contacted to find out the port.
        `protocol` - `Protocol` to be used for ONC/RPC calls.
      Throws:
        `OncRpcException` - if an ONC/RPC error occurs.
        `java.io.IOException` - if an I/O error occurs.

    - #### close

          public void close()
                     throws OncRpcException

      Close the connection to an ONC/RPC server and free all network-related resources. Well -- at least hope, that the Java VM will sometimes free some resources. Sigh.
      Throws:
        `OncRpcException` - if an ONC/RPC error occurs.

    - #### call

          public void call​(int procedureNumber,
                           XdrAble params,
                           XdrAble result)
                    throws OncRpcException

      Calls a remote procedure on an ONC/RPC server.

      The `OncRpcUdpClient` uses a similar timeout scheme as the genuine Sun C implementation of ONC/RPC: it starts with a timeout of one second when waiting for a reply. If no reply is received within this time frame, the client doubles the timeout, sends a new request and then waits again for a reply. In every case the client will wait no longer than the total timeout set through the `setTimeout(int)` method.

      Parameters:
        `procedureNumber` - Procedure number of the procedure to call.
        `params` - The parameters of the procedure to call, contained in an object which implements the `XdrAble` interface.
        `result` - The object receiving the result of the procedure call.
      Throws:
        `OncRpcException` - if an ONC/RPC error occurs.

    - #### call

          public abstract void call​(int procedureNumber,
                                    int versionNumber,
                                    XdrAble parameters,
                                    XdrAble result)
                             throws OncRpcException

      Calls a remote procedure on an ONC/RPC server.
      Parameters:
        `procedureNumber` - Procedure number of the procedure to call.
        `versionNumber` - Protocol version number.
        `parameters` - The parameters of the procedure to call, contained in an object which implements the `XdrAble` interface.
        `result` - The object receiving the result of the procedure call.
      Throws:
        `OncRpcException` - if an ONC/RPC error occurs.

    - #### setTimeout

          public void setTimeout​(int milliseconds)

      Set the timout for remote procedure calls to wait for an answer from the ONC/RPC server. If the timeout expires, `call(int, XdrAble, XdrAble)` will raise a `InterruptedIOException`. The default timeout value is 30 seconds (30,000 milliseconds). The timeout must be > 0. A timeout of zero indicated batched calls, for which no reply message is expected.
      Parameters:
        `milliseconds` - Timeout in milliseconds. A timeout of zero indicates batched calls.

    - #### getTimeout

          public int getTimeout()

      Retrieve the current timeout set for remote procedure calls. A timeout of zero indicates batching calls (no reply message is expected).
      Returns:
        Current timeout.

    - #### getProgram

          public int getProgram()

      Returns the program number specified when creating this client.
      Returns:
        ONC/RPC program number.

    - #### getVersion

          public int getVersion()

      Returns the version number specified when creating this client.
      Returns:
        ONC/RPC version number of ONC/RPC program.

    - #### getHost

          public java.net.InetAddress getHost()

      Returns the IP address of the server's host this client is connected to.
      Returns:
        IP address of host.

    - #### getPort

          public int getPort()

      Returns port number of the server this client is connected to.
      Returns:
        port number of ONC/RPC server.

    - #### setAuth

          public void setAuth​(OncRpcClientAuth auth)

      Sets the authentication to be used when making ONC/RPC calls.
      Parameters:
        `auth` - Authentication protocol handling object encapsulating authentication information.

    - #### getAuth

          public OncRpcClientAuth getAuth()

      Returns the current authentication.
      Returns:
        Authentication protocol handling object encapsulating authentication information.

    - #### setCharacterEncoding

          public abstract void setCharacterEncoding​(java.lang.String characterEncoding)

      Set the character encoding for (de-)serializing strings.
      Parameters:
        `characterEncoding` - the encoding to use for (de-)serializing strings. If `null`, the system's default encoding is to be used.

    - #### getCharacterEncoding

          public abstract java.lang.String getCharacterEncoding()

      Get the character encoding for (de-)serializing strings.
      Returns:
        the encoding currently used for (de-)serializing strings. If `null`, then the system's default encoding is used.

    - #### nextXid

          protected void nextXid()

      Create next message identifier. Message identifiers are used to match corresponding ONC/RPC call and reply messages.