xref: /onnv-gate/usr/src/lib/libslp/javalib/com/sun/slp/SrvLocHeader.java (revision 7298:b69e27387f74)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7298SMark.J.Nelson@Sun.COM  * Common Development and Distribution License (the "License").
6*7298SMark.J.Nelson@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
220Sstevel@tonic-gate  * Copyright 2001-2002 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate //  SrvLocHeader.java: Abstract superclass for SLP Headers
280Sstevel@tonic-gate //  Author:           James Kempf
290Sstevel@tonic-gate //  Created On:       Mon Sep 14 12:47:20 1998
300Sstevel@tonic-gate //  Last Modified By: James Kempf
310Sstevel@tonic-gate //  Last Modified On: Mon Nov 23 14:32:50 1998
320Sstevel@tonic-gate //  Update Count:     55
330Sstevel@tonic-gate //
340Sstevel@tonic-gate 
350Sstevel@tonic-gate package com.sun.slp;
360Sstevel@tonic-gate 
370Sstevel@tonic-gate import java.util.*;
380Sstevel@tonic-gate import java.net.*;
390Sstevel@tonic-gate import java.io.*;
400Sstevel@tonic-gate 
410Sstevel@tonic-gate /**
420Sstevel@tonic-gate  * SrvLocHeader handles different versions of the SLP header. Clients
430Sstevel@tonic-gate  * call the instance methods returned by newInstance(). If no version
440Sstevel@tonic-gate  * specific subclass exists for the version number, null is returned
450Sstevel@tonic-gate  * from newInstance. Parsing of the header and message bodies, and
460Sstevel@tonic-gate  * creation of error replies are handled by the version specific
470Sstevel@tonic-gate  * subclasses. We also let the SrvLocHeader serve as a SrvLocMsg object
480Sstevel@tonic-gate  * to handle the SrvAck, which only has an error code.
490Sstevel@tonic-gate  *
500Sstevel@tonic-gate  * @author James Kempf
510Sstevel@tonic-gate  */
520Sstevel@tonic-gate 
530Sstevel@tonic-gate abstract class SrvLocHeader extends Object implements SrvLocMsg, Cloneable {
540Sstevel@tonic-gate 
550Sstevel@tonic-gate     // Table of header classes. Keys are the version number.
560Sstevel@tonic-gate 
570Sstevel@tonic-gate     private static final Hashtable classTable = new Hashtable();
580Sstevel@tonic-gate 
590Sstevel@tonic-gate     // Offset to XID.
600Sstevel@tonic-gate 
610Sstevel@tonic-gate     static final int XID_OFFSET = 10;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate     // Common constants and instance variables.
640Sstevel@tonic-gate 
650Sstevel@tonic-gate     // Number of bytes in the version and function fields.
660Sstevel@tonic-gate 
670Sstevel@tonic-gate     static int VERSION_FUNCTION_BYTES = 2;
680Sstevel@tonic-gate 
690Sstevel@tonic-gate     // SLP function codes. Even though SAAdvert isn't in all versions,
700Sstevel@tonic-gate     //  we include it here.
710Sstevel@tonic-gate 
720Sstevel@tonic-gate     static final int SrvReq  = 1;
730Sstevel@tonic-gate     static final int SrvRply = 2;
740Sstevel@tonic-gate     static final int SrvReg = 3;
750Sstevel@tonic-gate     static final int SrvDereg = 4;
760Sstevel@tonic-gate     static final int SrvAck = 5;
770Sstevel@tonic-gate     static final int AttrRqst = 6;
780Sstevel@tonic-gate     static final int AttrRply = 7;
790Sstevel@tonic-gate     static final int DAAdvert = 8;
800Sstevel@tonic-gate     static final int SrvTypeRqst = 9;
810Sstevel@tonic-gate     static final int SrvTypeRply = 10;
820Sstevel@tonic-gate     static final int SAAdvert = 11;
830Sstevel@tonic-gate 
840Sstevel@tonic-gate     static final String[] functionCodeAbbr = {
850Sstevel@tonic-gate 	"0",
860Sstevel@tonic-gate 	"SrvReq",
870Sstevel@tonic-gate 	"SrvRply",
880Sstevel@tonic-gate 	"SrvReg",
890Sstevel@tonic-gate 	"SrvDereg",
900Sstevel@tonic-gate 	"SrvAck",
910Sstevel@tonic-gate 	"AttrRqst",
920Sstevel@tonic-gate 	"AttrRply",
930Sstevel@tonic-gate 	"DAAdvert",
940Sstevel@tonic-gate 	"SrvTypeRqst",
950Sstevel@tonic-gate 	"SrvTypeRply",
960Sstevel@tonic-gate 	"SAAdvert",
970Sstevel@tonic-gate     };
980Sstevel@tonic-gate 
990Sstevel@tonic-gate     // Sizes of data items.
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate     protected static final int BYTE_SIZE = 1;
1020Sstevel@tonic-gate     protected static final int SHORT_SIZE = 2;
1030Sstevel@tonic-gate     protected static final int INT24_SIZE = 3;
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate     //
1060Sstevel@tonic-gate     // Header instance variables.
1070Sstevel@tonic-gate     //
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate     // Unprotected for less code.
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate     int    version = 0;			// version number
1120Sstevel@tonic-gate     int    functionCode = 0;		// function code
1130Sstevel@tonic-gate     int    length = 0;			// packet length
1140Sstevel@tonic-gate     short  xid = 0;			// transaction id
1150Sstevel@tonic-gate     short  errCode =
1160Sstevel@tonic-gate 	ServiceLocationException.OK;	// not applicable to start
1170Sstevel@tonic-gate     Locale locale = Defaults.locale;	// language locale
1180Sstevel@tonic-gate     Vector previousResponders = null;	// list of previous responders
1190Sstevel@tonic-gate     Vector scopes = null;		// list of scopes
1200Sstevel@tonic-gate     boolean overflow = false;		// Overflow flag
1210Sstevel@tonic-gate     boolean fresh = false;		// Fresh flag
1220Sstevel@tonic-gate     boolean mcast = false;		// Mulitcast flag.
1230Sstevel@tonic-gate     byte[] payload = new byte[0];	// bytes of outgoing payload,
1240Sstevel@tonic-gate     int nbytes = 0;			// number of bytes processed
1250Sstevel@tonic-gate     int packetLength = 0;		// length of packet.
1260Sstevel@tonic-gate     int iNumReplies = 0;		// number of replies.
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate     protected static short uniqueXID = 0;	// outgoing transaction id.
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate     // Message description.
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate     private String msgType;
1340Sstevel@tonic-gate     private String msgDescription;
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 
SrvLocHeader()1370Sstevel@tonic-gate     SrvLocHeader() {
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	packetLength = SLPConfig.getSLPConfig().getMTU();
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate     }
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate     //
1440Sstevel@tonic-gate     // SrvLocMsg Implementation.
1450Sstevel@tonic-gate     //
1460Sstevel@tonic-gate 
getHeader()1470Sstevel@tonic-gate     public SrvLocHeader getHeader() {
1480Sstevel@tonic-gate 	return this;
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate     }
1510Sstevel@tonic-gate 
getErrorCode()1520Sstevel@tonic-gate     public short getErrorCode() {
1530Sstevel@tonic-gate 	return errCode;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate     }
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate     // Return number of replies to this message.
1580Sstevel@tonic-gate 
getNumReplies()1590Sstevel@tonic-gate     public int getNumReplies() {
1600Sstevel@tonic-gate 	return iNumReplies;
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate     }
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate     //
1650Sstevel@tonic-gate     // SrvLocHeader Interface.
1660Sstevel@tonic-gate     //
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate     // Register a new header class for version. Serious error, causing
1690Sstevel@tonic-gate     //  program termination, if we can't find it.
1700Sstevel@tonic-gate 
addHeaderClass(String className, int version)1710Sstevel@tonic-gate     static void addHeaderClass(String className, int version) {
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	try {
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	    Class headerClass = Class.forName(className);
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	    classTable.put(new Integer(version), headerClass);
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	} catch (ClassNotFoundException ex) {
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	    Assert.slpassert(false,
1820Sstevel@tonic-gate 			  "no_class",
1830Sstevel@tonic-gate 			  new Object[] {className});
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 	}
1860Sstevel@tonic-gate     }
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate     // Create a version specific instance. We use a naming convention
1890Sstevel@tonic-gate     //  to identify the version specific classes used to create the
1900Sstevel@tonic-gate     //  instance.
1910Sstevel@tonic-gate 
newInstance(int version)1920Sstevel@tonic-gate     static SrvLocHeader newInstance(int version) {
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	try {
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 	    // Get header class.
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	    Class hdrClass = (Class)classTable.get(new Integer(version));
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	    if (hdrClass == null) {
2010Sstevel@tonic-gate 		return null;
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 	    }
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	    SrvLocHeader hdr = (SrvLocHeader)hdrClass.newInstance();
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	    return hdr;
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	} catch (Exception ex) {
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	    SLPConfig.getSLPConfig().writeLog("slh_creation_exception",
2120Sstevel@tonic-gate 					      new Object[] {
2130Sstevel@tonic-gate 		new Integer(version),
2140Sstevel@tonic-gate 		    ex,
2150Sstevel@tonic-gate 		    ex.getMessage()});
2160Sstevel@tonic-gate 	    return null;
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	}
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate     }
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate     // Parse the incoming stream to obtain the header.
2230Sstevel@tonic-gate 
parseHeader(int functionCode, DataInputStream dis)2240Sstevel@tonic-gate     abstract void parseHeader(int functionCode, DataInputStream dis)
2250Sstevel@tonic-gate 	throws ServiceLocationException, IOException, IllegalArgumentException;
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate     // Parse the incoming stream to obtain the message.
2280Sstevel@tonic-gate 
parseMsg(DataInputStream dis)2290Sstevel@tonic-gate     abstract SrvLocMsg parseMsg(DataInputStream dis)
2300Sstevel@tonic-gate 	throws ServiceLocationException, IOException, IllegalArgumentException;
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate     // Externalize the message.
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate     abstract void
externalize(ByteArrayOutputStream baos, boolean multicast, boolean isTCP)2350Sstevel@tonic-gate 	externalize(ByteArrayOutputStream baos,
2360Sstevel@tonic-gate 		    boolean multicast,
2370Sstevel@tonic-gate 		    boolean isTCP)
2380Sstevel@tonic-gate 	throws ServiceLocationException;
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate     // Return the appropriately versioned DAAdvert.
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate     abstract SDAAdvert
getDAAdvert(short xid, long timestamp, ServiceURL url, Vector scopes, Vector attrs)2430Sstevel@tonic-gate 	getDAAdvert(short xid,
2440Sstevel@tonic-gate 		    long timestamp,
2450Sstevel@tonic-gate 		    ServiceURL url,
2460Sstevel@tonic-gate 		    Vector scopes,
2470Sstevel@tonic-gate 		    Vector attrs)
2480Sstevel@tonic-gate 	throws ServiceLocationException;
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate     //
2510Sstevel@tonic-gate     // Methods that some subclasses may reimplement.
2520Sstevel@tonic-gate     //
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate     // Parse any options.
2550Sstevel@tonic-gate 
parseOptions(DataInputStream dis)2560Sstevel@tonic-gate     void parseOptions(DataInputStream dis)
2570Sstevel@tonic-gate 	throws ServiceLocationException,
2580Sstevel@tonic-gate 	       IOException,
2590Sstevel@tonic-gate 	       IllegalArgumentException {
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate     }
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate     // Create an error reply for this message. This reply will be appropriate
2640Sstevel@tonic-gate     //  for the server to send back to the client. Default is to do nothing,
2650Sstevel@tonic-gate     //  which is the code for the client.
2660Sstevel@tonic-gate 
makeErrorReply(Exception ex)2670Sstevel@tonic-gate     SrvLocMsg makeErrorReply(Exception ex) {
2680Sstevel@tonic-gate 	return null;
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate     }
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate     //
2730Sstevel@tonic-gate     //  Common utilities for all versions.
2740Sstevel@tonic-gate     //
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate     // Set the packet length to the incoming value.
2770Sstevel@tonic-gate 
setPacketLength(int newLength)2780Sstevel@tonic-gate     void setPacketLength(int newLength) {
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	if (newLength > 0) {
2810Sstevel@tonic-gate 	    packetLength = newLength;
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	}
2840Sstevel@tonic-gate     }
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate     // Add an Internet address to the previous responders list.
2870Sstevel@tonic-gate 
addPreviousResponder(InetAddress addr)2880Sstevel@tonic-gate     void addPreviousResponder(InetAddress addr) {
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	String hostAddr = addr.getHostAddress();
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	Assert.slpassert((previousResponders != null),
2930Sstevel@tonic-gate 		      "prev_resp_reply",
2940Sstevel@tonic-gate 		      new Object[0]);
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	if (!previousResponders.contains(hostAddr)) {
2970Sstevel@tonic-gate 	    previousResponders.addElement(hostAddr);
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	}
3000Sstevel@tonic-gate     }
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate     // Get a unique transaction id.
3030Sstevel@tonic-gate 
getUniqueXID()3040Sstevel@tonic-gate     synchronized static short getUniqueXID() {
3050Sstevel@tonic-gate 	if (uniqueXID == 0) {
3060Sstevel@tonic-gate 	    Random r = new Random();
3070Sstevel@tonic-gate 	    uniqueXID = (short)(r.nextInt() &0xFFFF);
3080Sstevel@tonic-gate 	}
3090Sstevel@tonic-gate 	uniqueXID++;
3100Sstevel@tonic-gate 	return (short)(uniqueXID & 0xFFFF);
3110Sstevel@tonic-gate     }
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate     // Parse 2-byte integer, bump byte count.
3140Sstevel@tonic-gate 
getInt(DataInputStream dis)3150Sstevel@tonic-gate     int getInt(DataInputStream dis)
3160Sstevel@tonic-gate 	throws ServiceLocationException, IOException {
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	int ret = getInteger(dis);
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	nbytes += SHORT_SIZE;
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	return ret;
3230Sstevel@tonic-gate     }
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate     // Parse a 2-byte integer from the input stream.
3270Sstevel@tonic-gate 
getInteger(DataInputStream dis)3280Sstevel@tonic-gate     static int getInteger(DataInputStream dis)
3290Sstevel@tonic-gate 	throws ServiceLocationException, IOException {
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 	byte[] b = new byte[2];
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	dis.readFully(b, 0, 2);
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate 	int x = (int)((char)b[0] & 0xFF);
3360Sstevel@tonic-gate 	int y = (int)((char)b[1] & 0xFF);
3370Sstevel@tonic-gate 	int z = x << 8;
3380Sstevel@tonic-gate 	z += y;
3390Sstevel@tonic-gate 	return z;
3400Sstevel@tonic-gate     }
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate     // Parse 2-byte integer, bump byte count.
3430Sstevel@tonic-gate 
putInt(int z, ByteArrayOutputStream baos)3440Sstevel@tonic-gate     void putInt(int z, ByteArrayOutputStream baos) {
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 	putInteger(z, baos);
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 	nbytes += SHORT_SIZE;
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate     }
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate     // Parse a 2-byte integer to the output stream.
3530Sstevel@tonic-gate 
putInteger(int z, ByteArrayOutputStream baos)3540Sstevel@tonic-gate     static void putInteger(int z, ByteArrayOutputStream baos) {
3550Sstevel@tonic-gate 	baos.write((byte) ((0xFF00 & z)>>8));
3560Sstevel@tonic-gate 	baos.write((byte) (0xFF & z));
3570Sstevel@tonic-gate     }
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate     // Parse a 3-byte integer from the byte input stream.
3610Sstevel@tonic-gate 
getInt24(DataInputStream dis)3620Sstevel@tonic-gate     protected int getInt24(DataInputStream dis)
3630Sstevel@tonic-gate 	throws ServiceLocationException, IOException {
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	byte[] b = new byte[3];
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 	dis.readFully(b, 0, 3);
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	int w = (int)((char)b[0] & 0xFF);
3700Sstevel@tonic-gate 	int x = (int)((char)b[1] & 0xFF);
3710Sstevel@tonic-gate 	int y = (int)((char)b[2] & 0xFF);
3720Sstevel@tonic-gate 	int z = w << 16;
3730Sstevel@tonic-gate 	z += x << 8;
3740Sstevel@tonic-gate 	z += y;
3750Sstevel@tonic-gate 	nbytes += 3;
3760Sstevel@tonic-gate 	return z;
3770Sstevel@tonic-gate     }
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate     // Parse a 3-byte integer to the output stream.
3800Sstevel@tonic-gate 
putInt24(int z, ByteArrayOutputStream baos)3810Sstevel@tonic-gate     protected void putInt24(int z, ByteArrayOutputStream baos) {
3820Sstevel@tonic-gate 	baos.write((byte) ((0xFF0000 & z) >> 16));
3830Sstevel@tonic-gate 	baos.write((byte) ((0xFF00 & z)>>8));
3840Sstevel@tonic-gate 	baos.write((byte) (0xFF & z));
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 	nbytes += 3;
3870Sstevel@tonic-gate     }
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate     // Parse string, bump byte count. Use UTF8 encoding.
3910Sstevel@tonic-gate 
getString(StringBuffer buf, DataInputStream dis)3920Sstevel@tonic-gate     byte[] getString(StringBuffer buf, DataInputStream dis)
3930Sstevel@tonic-gate 	throws ServiceLocationException, IOException {
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 	byte[] ret = getStringField(buf, dis, Defaults.UTF8);
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	nbytes += ret.length + SHORT_SIZE;
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	return ret;
4000Sstevel@tonic-gate     }
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate     // Parse a string with an initial length from the input stream.
4030Sstevel@tonic-gate     //  Convert it to the proper encoding. Return the raw bytes for
4040Sstevel@tonic-gate     //  auth block creation.
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate     static byte[]
getStringField(StringBuffer buf, DataInputStream dis, String encoding)4070Sstevel@tonic-gate 	getStringField(StringBuffer buf, DataInputStream dis, String encoding)
4080Sstevel@tonic-gate 	throws ServiceLocationException, IOException {
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	// Clear out buffer first.
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 	buf.setLength(0);
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 	// First get the length.
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	int i, n = 0;
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	n = getInteger(dis);
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	// Now get the bytes.
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 	byte[] bytes = new byte[n];
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 	dis.readFully(bytes, 0, n);
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 	// Convert to string and return.
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 	buf.append(getBytesString(bytes, encoding));
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 	return bytes;
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate     }
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate     // Parse out string, bump byte count. Use UTF8 encoding.
4350Sstevel@tonic-gate 
putString(String string, ByteArrayOutputStream baos)4360Sstevel@tonic-gate     byte[] putString(String string, ByteArrayOutputStream baos) {
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate 	byte[] bytes = putStringField(string, baos, Defaults.UTF8);
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	nbytes += bytes.length + SHORT_SIZE;
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	return bytes;
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate     }
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate     // Put a string with an initial length into the byte stream, converting
4470Sstevel@tonic-gate     //  into the proper encoding.
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate     static byte[]
putStringField(String string, ByteArrayOutputStream baos, String encoding)4500Sstevel@tonic-gate 	putStringField(String string,
4510Sstevel@tonic-gate 		       ByteArrayOutputStream baos,
4520Sstevel@tonic-gate 		       String encoding) {
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 	byte[] bytes = getStringBytes(string, encoding);
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	// Put out the string's length in the encoding.
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	putInteger(bytes.length, baos);
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	// Now really write out the bytes.
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	baos.write(bytes, 0, bytes.length);
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate 	return bytes;
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate     }
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate     // Convert a Unicode string into encoded bytes.
4690Sstevel@tonic-gate 
getStringBytes(String string, String encoding)4700Sstevel@tonic-gate     static byte[] getStringBytes(String string, String encoding) {
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate 	try {
4730Sstevel@tonic-gate 	    return string.getBytes(encoding);
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 	} catch (UnsupportedEncodingException ex) {
4760Sstevel@tonic-gate 	    return  new byte[0];  // won't happen, hopefully...
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	}
4790Sstevel@tonic-gate     }
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate     // Convert bytes into a Unicode string.
4820Sstevel@tonic-gate 
getBytesString(byte[] bytes, String encoding)4830Sstevel@tonic-gate     static String getBytesString(byte[] bytes, String encoding) {
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 	try {
4860Sstevel@tonic-gate 	    return new String(bytes, encoding);
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 	} catch (UnsupportedEncodingException ex) {
4890Sstevel@tonic-gate 	    return "";  // won't happen, hopefully ...
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	}
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate     }
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate     // Parse a comma separated list of strings from the vector into the
4960Sstevel@tonic-gate     //  output stream.
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate     protected byte[]
parseCommaSeparatedListOut(Vector v, ByteArrayOutputStream baos)4990Sstevel@tonic-gate 	parseCommaSeparatedListOut(Vector v,
5000Sstevel@tonic-gate 				   ByteArrayOutputStream baos) {
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	return putString(vectorToCommaSeparatedList(v), baos);
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate     }
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate     /**
5070Sstevel@tonic-gate      * Create a comma separated list of strings out of the vector.
5080Sstevel@tonic-gate      *
5090Sstevel@tonic-gate      * @param v A Vector of strings.
5100Sstevel@tonic-gate      */
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate     static String
vectorToCommaSeparatedList(Vector v)5130Sstevel@tonic-gate 	vectorToCommaSeparatedList(Vector v) {
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 	// Construct in a string buffer first.
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	int i, n = v.size();
5180Sstevel@tonic-gate 	StringBuffer buf = new StringBuffer();
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
5220Sstevel@tonic-gate 	    String string = (String)v.elementAt(i);
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate 	    // Add comma for previous one if we need it.
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 	    if (i != 0) {
5270Sstevel@tonic-gate 		buf.append(',');
5280Sstevel@tonic-gate 	    }
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	    buf.append(string);
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 	}
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	// Return the bytes.
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 	return buf.toString();
5370Sstevel@tonic-gate     }
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate     /**
5400Sstevel@tonic-gate      * @parameter The string has the format = STRING *("," STRING)
5410Sstevel@tonic-gate      * @parameter A boolean indicating whether parens should be ignored or
5420Sstevel@tonic-gate      * 		used for grouping.
5430Sstevel@tonic-gate      * @return  A vector (of Strings) based upon the (comma delimited) string.
5440Sstevel@tonic-gate      */
parseCommaSeparatedListIn(String s, boolean ignoreParens)5450Sstevel@tonic-gate     static Vector parseCommaSeparatedListIn(String s, boolean ignoreParens)
5460Sstevel@tonic-gate 	throws ServiceLocationException {
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 	if (s == null)
5490Sstevel@tonic-gate 	    return new Vector();
5500Sstevel@tonic-gate 	if (s.length() == 0)
5510Sstevel@tonic-gate 	    return new Vector();
5520Sstevel@tonic-gate 	StringTokenizer st = new StringTokenizer(s, ",()", true);
5530Sstevel@tonic-gate 	try {
5540Sstevel@tonic-gate 	    int level = 0;
5550Sstevel@tonic-gate 	    String el = "";
5560Sstevel@tonic-gate 	    Vector v = new Vector();
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 	    while (st.hasMoreElements()) {
5590Sstevel@tonic-gate 		String tok = st.nextToken();
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 		// It's an open paren, so begin collecting.
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 		if (tok.equals("(")) {
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 		    // Increment the level if not ignoring parens, add to token
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate 		    if (!ignoreParens) {
5680Sstevel@tonic-gate 			level++;
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 		    }
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 		    el += tok;
5730Sstevel@tonic-gate 
5740Sstevel@tonic-gate 		} else if (tok.equals(")")) {
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate 		    // Decrement level if not ignoring parens.
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate 		    if (!ignoreParens) {
5790Sstevel@tonic-gate 			level--;
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 		    }
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 		    el += tok;
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 		} else if (tok.equals(",")) {
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 		    // Add if collecting.
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate 		    if (level != 0) {
5900Sstevel@tonic-gate 			el += tok;
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate 		    } else {
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 			// Check for empty token.
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 			if (el.length() <= 0) {
5970Sstevel@tonic-gate 			    throw
5980Sstevel@tonic-gate 				new ServiceLocationException(
5990Sstevel@tonic-gate 					ServiceLocationException.PARSE_ERROR,
6000Sstevel@tonic-gate 					"csl_syntax_error",
6010Sstevel@tonic-gate 					new Object[] {s});
6020Sstevel@tonic-gate 			}
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 			// If not collecting, then close off the element.
6050Sstevel@tonic-gate 
6060Sstevel@tonic-gate 			v.addElement(el);
6070Sstevel@tonic-gate 			el = "";
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 		    }
6100Sstevel@tonic-gate 		} else {
6110Sstevel@tonic-gate 		    el += tok;
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate 		}
6140Sstevel@tonic-gate 	    }
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 	    // Add last token, but check first for empty token.
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 	    if (el.length() <= 0) {
6190Sstevel@tonic-gate 		throw
6200Sstevel@tonic-gate 		    new ServiceLocationException(
6210Sstevel@tonic-gate 				ServiceLocationException.PARSE_ERROR,
6220Sstevel@tonic-gate 				"csl_syntax_error",
6230Sstevel@tonic-gate 				new Object[] {s});
6240Sstevel@tonic-gate 	    }
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 	    v.addElement(el);
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate 	    // If we're still collecting on close, then there's a syntax error.
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate 	    if (level != 0) {
6310Sstevel@tonic-gate 		throw
6320Sstevel@tonic-gate 		    new ServiceLocationException(
6330Sstevel@tonic-gate 				ServiceLocationException.PARSE_ERROR,
6340Sstevel@tonic-gate 				"csl_syntax_error",
6350Sstevel@tonic-gate 				new Object[] {s});
6360Sstevel@tonic-gate 	    }
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate 	    return v;
6390Sstevel@tonic-gate 	} catch (NoSuchElementException nsee) {
6400Sstevel@tonic-gate 	    throw
6410Sstevel@tonic-gate 		new ServiceLocationException(
6420Sstevel@tonic-gate 				ServiceLocationException.PARSE_ERROR,
6430Sstevel@tonic-gate 				"csl_syntax_error",
6440Sstevel@tonic-gate 				new Object[] {s});
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 	}
6470Sstevel@tonic-gate     }
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate     // Allow clients to clone the header.
6500Sstevel@tonic-gate 
clone()6510Sstevel@tonic-gate     public Object clone()
6520Sstevel@tonic-gate 	throws CloneNotSupportedException {
6530Sstevel@tonic-gate 	SrvLocHeader hdr = (SrvLocHeader)super.clone();
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 	// Reinitialize some stuff. Subclasses must reimplement nbytes
6560Sstevel@tonic-gate 	//  header size calculation.
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate 	hdr.length = 0;
6590Sstevel@tonic-gate 	hdr.payload = new byte[0];
6600Sstevel@tonic-gate 	hdr.iNumReplies = 0;
6610Sstevel@tonic-gate 	// packetlength stays the same, we may be using the same transport.
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 	return hdr;
6640Sstevel@tonic-gate 
6650Sstevel@tonic-gate     }
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate     // Construct a description of the header. Messages add individual
6680Sstevel@tonic-gate     //  descriptions to this.
6690Sstevel@tonic-gate 
constructDescription(String msgType, String msgDescription)6700Sstevel@tonic-gate     protected void constructDescription(String msgType,
6710Sstevel@tonic-gate 					String msgDescription) {
6720Sstevel@tonic-gate 	this.msgType = msgType;
6730Sstevel@tonic-gate 	this.msgDescription = msgDescription;
6740Sstevel@tonic-gate     }
6750Sstevel@tonic-gate 
getMsgType()6760Sstevel@tonic-gate     public String getMsgType() {
6770Sstevel@tonic-gate 	if (msgType == null) {
6780Sstevel@tonic-gate 	    if (functionCode > 0 && functionCode < functionCodeAbbr.length) {
6790Sstevel@tonic-gate 		return functionCodeAbbr[functionCode];
6800Sstevel@tonic-gate 	    } else {
6810Sstevel@tonic-gate 		return String.valueOf(functionCode);
6820Sstevel@tonic-gate 	    }
6830Sstevel@tonic-gate 	} else {
6840Sstevel@tonic-gate 	    return msgType;
6850Sstevel@tonic-gate 	}
6860Sstevel@tonic-gate     }
6870Sstevel@tonic-gate 
getMsgDescription()6880Sstevel@tonic-gate     public String getMsgDescription() {
6890Sstevel@tonic-gate 	return (msgDescription == null) ? "" : msgDescription;
6900Sstevel@tonic-gate     }
6910Sstevel@tonic-gate }
692