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