package edu.vt.marian.uip; import java.io.*; import java.net.*; import java.util.*; import edu.vt.marian.common.*; /** class name: xdr class description: This class will deal with XDR stuff uses the services of class(es): none designer: Junni Fan (jfan@vt.edu) implementators: Junni Fan(jfan@vt.edu) finished time: 11/29/98 known bugs: JDK version: 1.1.6 side effects: */ public class xdr { // possible return values public final static int OK = 0; public final static int INVALID_PARAMETER = -1; public final static int ERROR_IO = -2; // this is the max length of string currently supported private final static int MAX_STRING_LENGTH = 100000; // this is just for debugging Debug debug; /** method description: xdr constructor uses the services of class(es): none input parameter(s): debug -- only for debugging output parameter(s): none return value: none synchronization consideration: none */ public xdr(Debug debug) { this.debug = debug; } /** method description: write an integer to the bos uses the services of class(es): none input parameter(s): debug -- only for debugging output parameter(s): none return value: OK -- the method is executed successfully INVALID_PARAMETER -- wrong parameter ERROR_IO -- error in io operation synchronization consideration: none */ public int integer_to_stream_in_xdr( int i, BufferedOutputStream bos ) { // error checking if ( bos == null ) { debug.dumpTrace( "xdr(integer_to_stream_in_xdr): bos is null" ); return INVALID_PARAMETER; } // convert i to 4 bytes byte[] b = new byte[4]; b[0] = (new Integer(i / 16777216)).byteValue(); i %= 16777216; b[1] = (new Integer(i / 65536)).byteValue(); i %= 65536; b[2] = (new Integer(i / 256)).byteValue(); i %= 256; b[3] = (new Integer(i)).byteValue(); // write out the integer try { bos.write(b, 0, 4); } catch (IOException e) { debug.dumpTrace("xdr(integer_to_stream_in_xdr): error write xdr integer to stream : exception is caught"); return ERROR_IO; } return OK; } /** method description: write a boolean to the bos uses the services of class(es): xdr::integer_to_stream_in_xdr input parameter(s): b -- the boolean to be written out bos -- output stream output parameter(s): none return value: OK -- the method is executed successfully INVALID_PARAMETER -- wrong parameter ERROR_IO -- error in io operation synchronization consideration: none */ public int bool_to_stream_in_xdr( boolean b, BufferedOutputStream bos ) { // error checking if ( bos == null ) { debug.dumpTrace( "xdr(bool_to_stream_in_xdr): bos is null" ); return INVALID_PARAMETER; } // write out the boolean if (b) { return integer_to_stream_in_xdr( 1, bos ); } else { return integer_to_stream_in_xdr( 0, bos ); } } /** method description: write a string to the bos uses the services of class(es): xdr::integer_to_stream_in_xdr input parameter(s): s -- the string to be written out bos -- output stream output parameter(s): none return value: OK -- the method is executed successfully INVALID_PARAMETER -- wrong parameter ERROR_IO -- error in io operation synchronization consideration: none */ public int string_to_stream_in_xdr( String s, BufferedOutputStream bos ) { // error checking if ( bos == null ) { debug.dumpTrace( "xdr(string_to_stream_in_xdr): bos is null" ); return INVALID_PARAMETER; } if ( s == null ) { debug.dumpTrace( "xdr(string_to_stream_in_xdr): string is null" ); return INVALID_PARAMETER; } // write out string length int return_code = integer_to_stream_in_xdr( s.length(), bos ); if ( return_code != OK ) { debug.dumpTrace( "xdr(string_to_stream_in_xdr): error when write out the length" ); return return_code; } // write out the string byte[] bs = s.getBytes(); try { bos.write(bs, 0, s.length()); } catch (IOException e) { debug.dumpTrace("xdr(string_to_stream_in_xdr): error when write out the string"); return ERROR_IO; } // pad the string to multiple of 4 int i = s.length() % 4; if (i != 0) { try { // add additional 0's to make it a multiple of 4 i = 4 - i; int j; bs[0] = (new Integer(0)).byteValue(); for (j = 0; j < i; j++) { bos.write(bs, 0, 1); } } catch (IOException e) { debug.dumpTrace("xdr(string_to_stream_in_xdr): error when write out padding bytes"); return ERROR_IO; } } return OK; } /** method description: read an integer from the bis uses the services of class(es): none input parameter(s): bis -- input stream output parameter(s): none return value: desired integer -- the integer to be read INVALID_PARAMETER -- wrong parameter ERROR_IO -- error in io operation synchronization consideration: none */ public int read_integer_from_stream( BufferedInputStream bis ) throws Exception { // error checking if ( bis == null ) { debug.dumpTrace( "xdr(read_integer): bis is null" ); throw new Exception(); } // read in the integer byte[] b = new byte[4]; int i = 0; int j1 = -1, j2 = -1, j3 = -1, j4 = -1; try { j1 = bis.read(); j2 = bis.read(); j3 = bis.read(); j4 = bis.read(); if ((j1 == -1) || (j2 == -1) || (j3 == -1) || (j4 == -1)) { // probably marian server closed connection debug.dumpTrace("xdr(read_integer_from_stream): socket closed by marian server"); throw new Exception(); } i = j1 * 16777216 + j2 * 65536 + j3 * 256 + j4; } catch (IOException e) { debug.dumpTrace("xdr(read_integer_from_stream): error -- catch exception"); throw new Exception(); } return i; } /** method description: read a boolean from the bis uses the services of class(es): xdr::read_integer_from_stream input parameter(s): bis -- input stream output parameter(s): none return value: desired boolean -- the boolean to be read, return false if error occured synchronization consideration: none */ public boolean read_bool_from_stream( BufferedInputStream bis ) throws Exception { int result; // error checking if ( bis == null ) { debug.dumpTrace("class xdr method read_bool_from_stream: bis is null" ); throw new Exception(); } result = read_integer_from_stream(bis); if ( result == 1 ) { return true; } else if ( result == 0 ) { return false; } else { debug.dumpTrace( "xdr(read_bool_from_stream): the value is not 0/1" ); return true; } } /** method description: read a string from the bis uses the services of class(es): xdr::read_integer_from_stream input parameter(s): bis -- input stream output parameter(s): none return value: desired string null -- if error occurred synchronization consideration: none */ public String read_string_from_stream( BufferedInputStream bis ) { // error checking if ( bis == null ) { debug.dumpTrace( "xdr(read_string_from_stream): bis is null" ); return null; } // first read out the length of the string int length; try { length = read_integer_from_stream(bis); } catch (Exception e) { debug.dumpTrace("class xdr, method read string from stream, error happened when reading the string length"); return null; } // then read out the string according to the length if (length < 0) { // something must be wrong debug.dumpTrace( "xdr(read_string_from_stream): length<0" ); return null; } if (length == 0) { // this is am empty string return new String(""); } if (length > MAX_STRING_LENGTH) { // string oversized, probably something wrong happened debug.dumpTrace("class xdr method read_string_from_stream, string oversized"); return null; } // the string contains some data byte[] b = new byte[length]; try { int i = length; // left string length to read int j = 0; // offset to begin reading int k; // character number read this time while (i > 0) { // the whole string has not been read out k = bis.read(b, j, i); if (k == -1) { debug.dumpTrace("xdr(read_string_from_stream): socket is closed by marian server"); return null; } i -= k; j += k; } } catch (Exception e) { debug.dumpTrace("xdr(read_string_from_stream): error -- exception is caught when read out string"); return null; } // eat up the padding data // the whole string has been read out now int i = length % 4; if (i != 0) { // read out additional 0's to set the beginning of next data i = 4 - i; try { for (int j = 0; j < i; j++) { bis.read(); } } catch (Exception e) { debug.dumpTrace("xdr(read_string_from_stream): error -- exception is caught when eat up the padding data"); return null; } } return new String(b); } /** method description: get byte number of an integer in xdr format uses the services of class(es): none input parameter(s): none output parameter(s): none return value: byte number of an integer in xdr synchronization consideration: none */ public int get_integer_size() { return 4; } /** method description: get byte number of a boolean in xdr format uses the services of class(es): xdr::get_integer_size input parameter(s): none output parameter(s): none return value: byte number of a boolean in xdr format synchronization consideration: none */ public int get_bool_size() { return get_integer_size(); } /** method description: get byte number of a string in xdr format uses the services of class(es): xdr::get_string_size input parameter(s): none output parameter(s): none return value: positive number -- byte number of a string in xdr format INVALID_PARAMETER -- wrong parameter synchronization consideration: none */ public int get_string_size( String s ) { // error checking if ( s == null ) { debug.dumpTrace( "xdr(get_str_size): string is null" ); return INVALID_PARAMETER; } // calculate the string length in xdr int size = get_integer_size(); // size of integer for string length size += s.length(); if ( s.length() % 4 != 0 ) { size += 4 - (s.length() % 4); } return size; } }