Package org.acplt.oncrpc
This package implements Sun's ONC/RPC Remote Procedure Call specification (see RFC 1831, RFC 1832, RFC 1833).
Functionality currently supported:
- RPC calls over TCP/IP as well as UDP/IP.
- RPC client functionality.
- RPC server functionality (see package org.acplt.oncrpc.server).
- Querying the ONC/RPC portmapper.
- jrpcgen-utility for converting x-files into Java classes.
- Support for authentication types
AUTH_NONE
,AUTH_UNIX
andAUTH_SHORT
on both the client and the server side.
To manually convert x-files into serializable Java classes, first map the primitive rpcgen data types (and thus the data types described in RFC 1832 to some extend) onto Java's primitive data types. The following table should help you doing this.
rpcgen / RFC 1832 | Java | |||
char (used as character) | 8 bits / platform dependent | byte | 8 bits | xdr.xdrEncodeByte(byte) byte = xdr.xdrDecodeByte() |
unsigned char (used as character) | 8 bits / platform dependent | byte | 8 bits | xdr.xdrEncodeByte(byte) byte = xdr.xdrDecodeByte() |
char (used as 8 bit quantitiy) | 8 bits / platform dependent | byte | 8 bits | xdr.xdrEncodeByte(byte) byte = xdr.xdrDecodeByte() |
unsigned char (used as 8 bit quantitiy) | 8 bits / platform dependent | byte | 8 bits | xdr.xdrEncodeByte(byte) byte = xdr.xdrDecodeByte() |
short | platform dependent | short | 16 bits | xdr.xdrEncodeShort(short) short = xdr.xdrDecodeShort() |
unsigned short | platform dependent | short | 16 bits | xdr.xdrEncodeShort(short) short = xdr.xdrDecodeShort() |
int | 32 bits | int | 32 bits | xdr.xdrEncodeInt(int) int = xdr.xdrDecodeInt() |
unsigned int | 32 bits | int | 32 bits | xdr.xdrEncodeInt(int) int = xdr.xdrDecodeInt() |
hyper | 64 bits | long | 64 bits | xdr.xdrEncodeLong(long) long = xdr.xdrDecodeLong() |
unsigned hyper | 64 bits | long | 64 bits | xdr.xdrEncodeLong(long) long = xdr.xdrDecodeLong() |
enum | 32 bits | int | 32 bits | xdr.xdrEncodeInt(int) int = xdr.xdrDecodeInt() |
bool | boolean | xdr.xdrEncodeBoolean(boolean) boolean = xdr.xdrDecodeBoolean() | ||
float | 32 bits | float | 32 bits | xdr.xdrEncodeFloat(float) float = xdr.xdrDecodeFloat() |
double | 64 bits | double | 64 bits | xdr.xdrEncodeDouble(double) double = xdr.xdrDecodeDouble() |
quadruple | 128 bits | n/a | ||
opaque[n] | exactly n octets | byte[] | n bytes | xdr.xdrEncodeOpaque(byte[]) byte[] = xdr.xdrDecodeOpaque(n) |
opaque<n> | 4 bytes size followed by at most n octets |
byte[] | ?? bytes | xdr.xdrEncodeDynamicOpaque(byte[]) byte[] = xdr.xdrDecodeDynamicOpaque() |
opaque<> | 4 bytes size followed by ?? octets |
byte[] | ?? bytes | xdr.xdrEncodeDynamicOpaque(byte[]) byte[] = xdr.xdrDecodeDynamicOpaque() |
string<n> | 4 bytes size followed by at most n octets |
String | ?? bytes | xdr.xdrEncodeString(String) String = xdr.xdrDecodeString() |
string<> | 4 bytes size followed by ?? octets |
String | ?? bytes | xdr.xdrEncodeString(String) String = xdr.xdrDecodeString() |
void | 0 bits | XdrVoid | xdrvoid.xdrEncode(xdr) xdrvoid.xdrDecode(xdr) |
The Remote Tea library also provides method to (de-) serialize vector data
types of variable length, as shown below. To (de-) derialize fixed-size vectors,
use the ...FixedVector()
variants and supply the protocol-defined
size of the vector -- see the next table but one.
rpcgen / RFC 1832 | Java | ||
opaque<> | 4 bytes size followed by ?? octets |
byte[] |
xdr.xdrEncodeDynamicOpaque(byte[]) byte[] = xdr.xdrDecodeDynamicOpaque() |
char<> char short<> | 4 bytes size followed by ?? chars |
byte[] |
xdr.xdrEncodeByteVector(byte[]) byte[] = xdr.xdrDecodeByteVector() |
short<> unsigned short<> | 4 bytes size followed by ?? shorts |
short[] |
xdr.xdrEncodeShortVector(short[]) short[] = xdr.xdrDecodeShortVector() |
int<> unsigned int<> | 4 bytes size followed by ?? ints |
int[] |
xdr.xdrEncodeIntVector(int[]) int[] = xdr.xdrDecodeIntVector() |
long<> unsigned long<> | 4 bytes size followed by ?? longs |
int[] |
xdr.xdrEncodeIntVector(int[]) int[] = xdr.xdrDecodeIntVector() |
hyper<> unsigned hyper<> | 4 bytes size followed by ?? hypers |
long[] |
xdr.xdrEncodeLongVector(long[]) long[] = xdr.xdrDecodeLongVector() |
enum<> | 4 bytes size followed by ?? enums |
int[] |
xdr.xdrEncodeIntVector(int[]) int[] = xdr.xdrDecodeIntVector() |
bool<> | 4 bytes size followed by ?? bools |
boolean[] |
xdr.xdrEncodeBooleanVector(boolean[]) boolean[] = xdr.xdrDecodeBooleanVector() |
float<> | 4 bytes size followed by ?? floats |
float[] |
xdr.xdrEncodeFloatVector(float[]) float[] = xdr.xdrDecodeFloatVector() |
double<> | 4 bytes size followed by ?? doubles |
double[] |
xdr.xdrEncodeDoubleVector(double[]) double[] = xdr.xdrDecodeDoubleVector() |
And now for (de-) serializing fixed-size vectors:
rpcgen / RFC 1832 | Java | ||
char[n] char short[n] | 4 bytes size followed by n chars |
byte[] |
xdr.xdrEncodeByteFixedVector(byte[], int n) byte[] = xdr.xdrDecodeByteFixedVector(int n) |
short[n] unsigned short[n] | 4 bytes size followed by n shorts |
short[] |
xdr.xdrEncodeShortFixedVector(short[], int n) short[] = xdr.xdrDecodeShortFixedVector(int n) |
int[n] unsigned int[n] | 4 bytes size followed by n ints |
int[] |
xdr.xdrEncodeIntFixedVector(int[], int n) int[] = xdr.xdrDecodeIntFixedVector(int n) |
long[n] unsigned long[n] | 4 bytes size followed by n longs |
int[] |
xdr.xdrEncodeIntFixedVector(int[], int n) int[] = xdr.xdrDecodeIntFixedVector(int n) |
hyper[n] unsigned hyper[n] | 4 bytes size followed by n hypers |
long[] |
xdr.xdrEncodeLongFixedVector(long[], int n) long[] = xdr.xdrDecodeLongFixedVector(int n) |
enum[n] | 4 bytes size followed by n enums |
int[] |
xdr.xdrEncodeIntFixedVector(int[], int n) int[] = xdr.xdrDecodeIntFixedVector(int n) |
bool[n] | 4 bytes size followed by n bools |
boolean[] |
xdr.xdrEncodeBooleanFixedVector(boolean[], int n) boolean[] = xdr.xdrDecodeBooleanFixedVector(int n) |
float[n] | 4 bytes size followed by n floats |
float[] |
xdr.xdrEncodeFloatFixedVector(float[], int n) float[] = xdr.xdrDecodeFloatFixedVector(int n) |
double[n] | 4 bytes size followed by n doubles |
double[] |
xdr.xdrEncodeDoubleFixedVector(double[], int n) double[] = xdr.xdrDecodeDoubleFixedVector(int n) |
For every structure you encounter in a .x file, write a Java class,
which implements the
XdrAble
interface. For instance,
taking this snippet from a rpcgen source file...
struct foo { int bar; float baz; struct foo *next; };
...struct foo
is translated into Java ONC/RPC babble as:
class foo implements XdrAble { // members of foo structure public int bar; public float baz; public foo next; // serialize / encode foo public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException { xdr.xdrEncodeInt(bar); xdr.xdrEncodeFloat(baz); if ( next == null ) { xdr.xdrEncodeBoolean(false); } else { xdr.xdrEncodeBoolean(true); next.xdrEncode(xdr); } } // deserialize / decode foo public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException { bar = xdr.xdrDecodeInt(); baz = xdr.xdrDecodeFloat(); if ( !xdr.xdrDecodeBoolean() ) { next = null; } else { next = new foo(); next.xdrDecode(xdr); } } }
The previous example also shows how to deal with pointers (eeek!) in .x files. The are simply transformed into references -- quite a difference, really.
Tanslating a descriminated union is typically done the simple and silly way. Silly, because unions can not really be represented in the Java language. You need to transform them into a class (structure) instead, and this will lead to a rather ugly form.
union foo switch (FOOTYPE type) { case BAR_CLASS: bar u_bar; case BAZ_CLASS: baz u_baz; }should become
class foo implements XdrAble { // descriminant value public int type; // arm declarations public bar u_bar; public baz u_baz; // descriminant-arm values public static int BAR_CLASS = 1; public static int BAZ_CLASS = 2; // serialize / encode foo public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException { xdr.xdrEncodeInt(type); switch ( type ) { case BAR_CLASS: u_bar.xdrEncode(xdr); break; case BAZ_CLASS: u_baz.xdrEncode(xdr); break; } } // deserialize / decode foo public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException { type = xdr.xdrDecodeInt(); switch ( type ) { case BAR_CLASS: u_bar = new bar(); u_bar.xdrDecode(xdr); break; case BAZ_CLASS: u_baz = new bar(); u_bar.xdrDecode(xdr); break; } } }
You can also take advantage of polymorphism when translating descriminated unions into a class hierarchy. You should then write an abstract base class with only one static member function capable of constructing the appropriate instance from the XDR stream. The tricky part about this is getting the descriminant value into the stream or out of it without having to duplicate the decoding code into the constructor. With the skeleton below you should be able to do this easily, but you should remember to never recycle an object reference and never deserialize the state of the object a second time from a XDR stream!
abstract class foobase implements XdrAble { // construct a bar, baz,... class from XDR stream public static foobase xdrNew(XdrDecodingStream xdr) throws OncRpcException, IOException { foobase obj = null; switch ( xdr.xdrDecodeInt() ) { case BAR_CLASS: obj = new bar(); break; case BAZ_CLASS: obj = new baz(); break; } obj.xdrDecode(xdr); return obj; } public abstract void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException; public abstract void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException; // descriminant values public static int BAR_CLASS = 1; public static int BAZ_CLASS = 2; } class bar extends foobase { public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException { // encode your members here... // dont forget to encode the descriminant value xdr.xdrEncodeInt(BAR_CLASS); xdr.xdrEncodeFloat(noah); } public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException { // decode your members here... // but *NEVER* decode the descriminant value noah = xdr.xdrDecodeFloat(); } }
This package is part of the ACPLT/KS ACPLTea Java Library package. (c) 1999, 2006 Harald Albrecht.
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program (see the file COPYING.LIB for more details); if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|