org.acplt.oncrpc
Class OncRpcClient

java.lang.Object
  extended by 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 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);
 

See Also:
OncRpcPortmapClient, OncRpcTcpClient, OncRpcUdpClient, OncRpcClientAuth

Field Summary
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
protected OncRpcClient(java.net.InetAddress host, int program, int version, int port, int protocol)
          Constructs an OncRpcClient object (the generic part).
 
Method Summary
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.