2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A *
2N/A */
2N/A
2N/A// SLPHeaderV1.java: SLPv1 Header.
2N/A// Author: James Kempf
2N/A// Created On: Thu Sep 10 15:12:14 1998
2N/A// Last Modified By: James Kempf
2N/A// Last Modified On: Wed Jan 20 15:38:07 1999
2N/A// Update Count: 59
2N/A//
2N/A
2N/Apackage com.sun.slp;
2N/A
2N/Aimport java.util.*;
2N/Aimport java.io.*;
2N/A
2N/A/**
2N/A * The SLPHeaderV1 class models the SLPv1 server side header.
2N/A *
2N/A * @author James Kempf
2N/A */
2N/A
2N/Aclass SLPHeaderV1 extends SrvLocHeader implements Cloneable {
2N/A
2N/A // Version number.
2N/A
2N/A static int VERSION = 1;
2N/A
2N/A // Function code for message reply.
2N/A
2N/A int replyFunctionCode = SrvLocHeader.SrvAck;
2N/A
2N/A // Various header flags.
2N/A
2N/A protected static final int NOFLAG = 0x00;
2N/A protected static final int OVERFLOW = 0x80;
2N/A protected static final int MONOLING = 0x40;
2N/A protected static final int URLSIG = 0x20;
2N/A protected static final int ATTRSIG = 0x10;
2N/A protected static final int FRESH = 0x08;
2N/A
2N/A protected static int LANG_CODE_BYTES = 2;
2N/A
2N/A protected static int HEADER_BYTES =
2N/A VERSION_FUNCTION_BYTES + LANG_CODE_BYTES + 8;
2N/A
2N/A // Characters to escape.
2N/A
2N/A final private static String UNESCAPABLE_CHARS = ",=!></*()";
2N/A final private static String ESCAPABLE_CHARS =
2N/A UNESCAPABLE_CHARS + "&#;";
2N/A
2N/A String charCode = IANACharCode.UTF8; // character encoding.
2N/A boolean monolingual = false; // monolingual flag.
2N/A
2N/A // Used to construct a header in SrvLocHeader.newInstance().
2N/A
2N/A SLPHeaderV1() {
2N/A super();
2N/A
2N/A version = VERSION;
2N/A
2N/A }
2N/A
2N/A // Assign reply code based on function code type, then use superclass
2N/A // method to parse header.
2N/A
2N/A void parseHeader(int functionCode, DataInputStream dis)
2N/A throws ServiceLocationException, IOException {
2N/A
2N/A this.functionCode = functionCode;
2N/A
2N/A // We ignore the error case here.
2N/A
2N/A switch (functionCode) {
2N/A
2N/A case SrvLocHeader.SrvReq:
2N/A replyFunctionCode = SrvLocHeader.SrvRply;
2N/A break;
2N/A
2N/A case SrvLocHeader.AttrRqst:
2N/A replyFunctionCode = SrvLocHeader.AttrRply;
2N/A break;
2N/A
2N/A case SrvLocHeader.SrvTypeRqst:
2N/A replyFunctionCode = SrvLocHeader.SrvTypeRply;
2N/A break;
2N/A
2N/A }
2N/A
2N/A length = getInt(dis);
2N/A byte flags = (byte) ((char)dis.read() & 0xFF);
2N/A nbytes++;
2N/A
2N/A overflow = ((flags & OVERFLOW) != 0x00);
2N/A fresh = false; // fresh gets set on output in SLPv1
2N/A monolingual = ((flags & MONOLING) != 0x00);
2N/A boolean urlAuth = ((flags & URLSIG) != 0x00);
2N/A boolean attrAuth = ((flags & ATTRSIG) != 0x00);
2N/A
2N/A // Security not handled for SLPv1.
2N/A
2N/A if (urlAuth || attrAuth) {
2N/A throw
2N/A new ServiceLocationException(
2N/A ServiceLocationException.AUTHENTICATION_FAILED,
2N/A "v1_no_security",
2N/A new Object[0]);
2N/A }
2N/A
2N/A int dialect = (int) ((char)dis.read() & 0xFF);
2N/A nbytes++;
2N/A
2N/A // Dialect must be zero.
2N/A
2N/A if (dialect != 0) {
2N/A throw
2N/A new ServiceLocationException(
2N/A ServiceLocationException.PARSE_ERROR,
2N/A "v1_nonzero_dialect",
2N/A new Object[0]);
2N/A
2N/A }
2N/A
2N/A byte a_bTemp[] = new byte[LANG_CODE_BYTES];
2N/A a_bTemp[0] = (byte) dis.read();
2N/A a_bTemp[1] = (byte) dis.read();
2N/A nbytes += 2;
2N/A
2N/A try {
2N/A locale = new Locale(new String(a_bTemp, IANACharCode.ASCII), "");
2N/A
2N/A } catch (UnsupportedEncodingException ex) {
2N/A
2N/A }
2N/A
2N/A int intCharCode = getInt(dis);
2N/A charCode = IANACharCode.decodeCharacterEncoding(intCharCode);
2N/A
2N/A xid = (short)getInt(dis);
2N/A
2N/A errCode = ServiceLocationException.OK;
2N/A }
2N/A
2N/A // Parse an incoming V1 message and return the SrvLocMsg object.
2N/A
2N/A SrvLocMsg parseMsg(DataInputStream dis)
2N/A throws ServiceLocationException,
2N/A IOException,
2N/A IllegalArgumentException {
2N/A
2N/A SrvLocMsg msg = null;
2N/A
2N/A // If this is a *multicast* request, we reject it except for DAAdvert.
2N/A // Multicast requests are only taken by SA servers.
2N/A
2N/A if (mcast && (functionCode != SrvLocHeader.DAAdvert)) {
2N/A return null;
2N/A
2N/A }
2N/A
2N/A // Switch and convert according to function code.
2N/A
2N/A switch (functionCode) {
2N/A
2N/A case SrvLocHeader.SrvReq:
2N/A msg = new SLPV1SSrvMsg(this, dis);
2N/A break;
2N/A
2N/A case SrvLocHeader.SrvReg:
2N/A msg = new SLPV1SSrvReg(this, dis);
2N/A break;
2N/A
2N/A case SrvLocHeader.SrvDereg:
2N/A msg = new SLPV1SSrvDereg(this, dis);
2N/A break;
2N/A
2N/A case SrvLocHeader.AttrRqst:
2N/A msg = new SLPV1SAttrMsg(this, dis);
2N/A break;
2N/A
2N/A case SrvLocHeader.SrvTypeRqst:
2N/A msg = new SLPV1SSrvTypeMsg(this, dis);
2N/A break;
2N/A
2N/A case SrvLocHeader.DAAdvert:
2N/A msg = new SLPV1CDAAdvert(this, dis);
2N/A break;
2N/A
2N/A default:
2N/A throw
2N/A new ServiceLocationException(
2N/A ServiceLocationException.PARSE_ERROR,
2N/A "function_code_error",
2N/A new Object[] {
2N/A new Integer(functionCode)});
2N/A
2N/A }
2N/A
2N/A // Check for size overflow.
2N/A
2N/A if (nbytes > length) {
2N/A throw
2N/A new ServiceLocationException(
2N/A ServiceLocationException.PARSE_ERROR,
2N/A "length_overflow",
2N/A new Object[] {
2N/A new Integer(nbytes), new Integer(length)});
2N/A
2N/A }
2N/A
2N/A return msg;
2N/A
2N/A }
2N/A
2N/A // Externalize the message by converting it to bytes and writing
2N/A // it to the output stream.
2N/A
2N/A public void
2N/A externalize(ByteArrayOutputStream baos, boolean mcast, boolean isTCP)
2N/A throws ServiceLocationException {
2N/A
2N/A // Need to put in the error code or previous responders.
2N/A
2N/A ByteArrayOutputStream fin = new ByteArrayOutputStream();
2N/A
2N/A if (functionCode == SrvLocHeader.SrvAck ||
2N/A functionCode == SrvLocHeader.SrvTypeRply ||
2N/A functionCode == SrvLocHeader.SrvRply ||
2N/A functionCode == SrvLocHeader.AttrRply ||
2N/A functionCode == SrvLocHeader.DAAdvert) {
2N/A putInt(errCode, fin);
2N/A
2N/A } else {
2N/A
2N/A // Parse out previous responders. Note there will only be some
2N/A // if the error code is not put out.
2N/A
2N/A if (previousResponders != null) {
2N/A parseCommaSeparatedListOut(previousResponders, fin);
2N/A
2N/A }
2N/A }
2N/A
2N/A // Parse payload out if error code is OK and payload is nonnull.
2N/A
2N/A if (payload != null && errCode == ServiceLocationException.OK) {
2N/A fin.write(payload, 0, payload.length);
2N/A }
2N/A
2N/A // Don't touch payload here, somebody may put in a previousResponder
2N/A // and resend the message.
2N/A
2N/A byte[] npayload = fin.toByteArray();
2N/A
2N/A // Set overflow flag if buffer is too large and this isn't going out
2N/A // via TCP.
2N/A
2N/A if (((npayload.length + 12) > SLPConfig.getSLPConfig().getMTU()) &&
2N/A !isTCP) {
2N/A overflow = true;
2N/A
2N/A }
2N/A
2N/A baos.write((byte) (0xFF & version));
2N/A nbytes++;
2N/A baos.write((byte) (0xFF & functionCode));
2N/A nbytes++;
2N/A
2N/A length = npayload.length +12; // the 12 is the length of this header!
2N/A
2N/A putInt(length, baos); // what about overflow???
2N/A
2N/A byte flags = 0X00;
2N/A
2N/A if (overflow) {
2N/A flags = (byte)(flags | OVERFLOW);
2N/A } else {
2N/A flags = (byte)(flags & ~OVERFLOW);
2N/A }
2N/A
2N/A if (monolingual) {
2N/A flags = (byte)(flags | MONOLING);
2N/A } else {
2N/A flags = (byte)(flags & ~MONOLING);
2N/A }
2N/A
2N/A if (fresh) {
2N/A flags = (byte)((flags | FRESH) & 0XFF);
2N/A } else {
2N/A flags = (byte)((flags & ~FRESH) & 0XFF);
2N/A }
2N/A
2N/A baos.write((byte) (0xFF & flags));
2N/A nbytes++;
2N/A baos.write((byte) (0xFF & 0)); // dialect...
2N/A nbytes++;
2N/A
2N/A String language = locale.getLanguage();
2N/A
2N/A baos.write((byte) (0xFF & language.charAt(0)));
2N/A baos.write((byte) (0xFF & language.charAt(1)));
2N/A nbytes += 2;
2N/A
2N/A int intCharCode = 0;
2N/A
2N/A try {
2N/A intCharCode = IANACharCode.encodeCharacterEncoding(charCode);
2N/A
2N/A } catch (ServiceLocationException ex) {
2N/A Assert.slpassert(false,
2N/A "v1_unsupported_encoding",
2N/A new Object[] {charCode});
2N/A
2N/A }
2N/A
2N/A putInt(intCharCode, baos);
2N/A putInt(xid, baos);
2N/A
2N/A // Write the body.
2N/A
2N/A baos.write(npayload, 0, npayload.length);
2N/A nbytes += npayload.length;
2N/A }
2N/A
2N/A // Create an error reply using the reply code. Calculate the
2N/A // error code using the exception.
2N/A
2N/A SrvLocMsg makeErrorReply(Exception ex) {
2N/A
2N/A // If this is a DAAdvert, then no error reply is returned
2N/A // because V1 doesn't support unicast SrvRqst for DAAdvert.
2N/A
2N/A if (functionCode == SrvLocHeader.DAAdvert) {
2N/A return null;
2N/A
2N/A }
2N/A
2N/A // Clone the header to make sure that everything else is the same.
2N/A // We don't want to use the same header because it may be tested
2N/A // elsewhere.
2N/A
2N/A SLPHeaderV1 hdr = null;
2N/A
2N/A try {
2N/A hdr = (SLPHeaderV1)this.clone();
2N/A
2N/A } catch (CloneNotSupportedException exx) {
2N/A
2N/A // We know we support it.
2N/A
2N/A }
2N/A
2N/A hdr.fresh = false;
2N/A hdr.overflow = false;
2N/A hdr.mcast = false;
2N/A hdr.functionCode = replyFunctionCode;
2N/A
2N/A // We should *not* be getting a null exception down this path!
2N/A
2N/A Assert.slpassert(ex != null,
2N/A "null_parameter",
2N/A new Object[] {ex});
2N/A
2N/A if (ex instanceof ServiceLocationException) {
2N/A
2N/A hdr.errCode = ((ServiceLocationException)ex).getErrorCode();
2N/A
2N/A // Handle monolingual bit here. If the exception is
2N/A // LANGUAGE_NOT_SUPPORTED and the message type is
2N/A // either SrvRqst or AttrRqst, then we simply return an
2N/A // empty message unless the monolingual flag is on.
2N/A
2N/A if (hdr.errCode ==
2N/A ServiceLocationException.LANGUAGE_NOT_SUPPORTED) {
2N/A
2N/A try {
2N/A
2N/A if (!hdr.monolingual) {
2N/A
2N/A if (hdr.functionCode == SrvLocHeader.SrvReq) {
2N/A
2N/A return SLPV1SSrvMsg.makeEmptyReply(hdr);
2N/A
2N/A } else if (hdr.functionCode == SrvLocHeader.AttrRqst) {
2N/A
2N/A return SLPV1SAttrMsg.makeEmptyReply(hdr);
2N/A
2N/A }
2N/A }
2N/A
2N/A } catch (ServiceLocationException exx) {
2N/A
2N/A hdr.monolingual = true;
2N/A hdr.makeErrorReply(exx);
2N/A
2N/A }
2N/A
2N/A // Otherwise, we just ignore it.
2N/A }
2N/A
2N/A // Anything over AUTHENTICATION_FAILED is an internal error in V1.
2N/A
2N/A if (hdr.errCode > ServiceLocationException.AUTHENTICATION_FAILED) {
2N/A hdr.errCode = ServiceLocationException.PARSE_ERROR;
2N/A
2N/A }
2N/A
2N/A } else if (ex instanceof IllegalArgumentException ||
2N/A ex instanceof IOException) {
2N/A hdr.errCode = ServiceLocationException.PARSE_ERROR;
2N/A
2N/A } else {
2N/A hdr.errCode = ServiceLocationException.PARSE_ERROR;
2N/A
2N/A }
2N/A
2N/A // Construct header description.
2N/A
2N/A hdr.constructDescription("SrvLocMsg", "");
2N/A
2N/A return hdr;
2N/A }
2N/A
2N/A // Return a reply header with flags properly set.
2N/A
2N/A SLPHeaderV1 makeReplyHeader() {
2N/A
2N/A SLPHeaderV1 hdr = null;
2N/A
2N/A try {
2N/A hdr = (SLPHeaderV1)this.clone();
2N/A
2N/A } catch (CloneNotSupportedException ex) {
2N/A
2N/A // We know that we support it.
2N/A }
2N/A
2N/A hdr.functionCode = replyFunctionCode;
2N/A hdr.length = 0;
2N/A hdr.previousResponders = null;
2N/A hdr.scopes = null;
2N/A hdr.overflow = false;
2N/A hdr.fresh = false;
2N/A hdr.mcast = false;
2N/A hdr.nbytes = 0;
2N/A
2N/A return hdr;
2N/A }
2N/A
2N/A // Return display string.
2N/A
2N/A public String toString() {
2N/A return
2N/A getMsgType() + ":version=``" + version + "''\n" +
2N/A " functionCode=``" + functionCode + "''\n" +
2N/A " length=``" + length + "''\n" +
2N/A " overflow=``" + overflow + "''\n" +
2N/A " mcast = ``" + mcast + "''\n" +
2N/A " fresh=``" + fresh + "''\n" +
2N/A " monolingual=``" + monolingual + "''\n" +
2N/A " charCode=``" + charCode + "''\n" +
2N/A " locale = ``" + locale + "''\n" +
2N/A " xid=``0x" + Integer.toHexString(xid) + "''\n" +
2N/A " errCode=``" + errCode + "''\n" +
2N/A " previousResponders=``" + previousResponders + "''\n" +
2N/A " scopes=``" + scopes + "''\n" +
2N/A getMsgDescription();
2N/A }
2N/A
2N/A //
2N/A // Validation Utilities.
2N/A //
2N/A
2N/A /**
2N/A * Validate the scope name to be sure it doesn't contain forbidden
2N/A * chars and isn't one of the reserved scope names.
2N/A */
2N/A
2N/A static void validateScope(String scope)
2N/A throws ServiceLocationException
2N/A {
2N/A if (scope.indexOf('/') != -1 || scope.indexOf(',') != -1 ||
2N/A scope.indexOf(':') != -1) {
2N/A throw new ServiceLocationException(
2N/A ServiceLocationException.PARSE_ERROR,
2N/A "v1_scope_char_res",
2N/A new Object[] {scope});
2N/A }
2N/A
2N/A // Check against reserved scope names.
2N/A
2N/A if (scope.equalsIgnoreCase("local") ||
2N/A scope.equalsIgnoreCase("remote")) {
2N/A throw new ServiceLocationException(
2N/A ServiceLocationException.PARSE_ERROR,
2N/A "v1_scope_name_res",
2N/A new Object[] {scope});
2N/A }
2N/A
2N/A }
2N/A
2N/A /**
2N/A * Remove IANA from the service type name.
2N/A *
2N/A * @param serviceType The service type and naming authority.
2N/A * @return The service type name with IANA removed.
2N/A */
2N/A
2N/A static String removeIANA(String serviceType) {
2N/A
2N/A // Substitute null string for IANA.
2N/A
2N/A int idx = 0;
2N/A
2N/A serviceType = serviceType.toLowerCase();
2N/A
2N/A if ((idx = serviceType.indexOf("." + ServiceType.IANA)) != -1) {
2N/A serviceType = serviceType.substring(0, idx);
2N/A
2N/A }
2N/A
2N/A return serviceType;
2N/A }
2N/A
2N/A // Check whether this is a vaild SLPv1 service type. Also remove
2N/A // IANA.
2N/A
2N/A static String checkServiceType(String stype)
2N/A throws ServiceLocationException {
2N/A
2N/A // Check for trailing colon and remove it.
2N/A
2N/A if (!stype.endsWith(":")) {
2N/A throw
2N/A new ServiceLocationException(
2N/A ServiceLocationException.PARSE_ERROR,
2N/A "v1_service_type_format",
2N/A new Object[] {stype});
2N/A
2N/A }
2N/A
2N/A String type = stype.substring(0, stype.length()-1);
2N/A
2N/A // Remove IANA.
2N/A
2N/A type = removeIANA(type);
2N/A
2N/A // Check syntax.
2N/A
2N/A ServiceType st = new ServiceType(type);
2N/A
2N/A // Reject if abstract type. SLPv1 doesn't handle
2N/A // abstract types.
2N/A
2N/A if (st.isAbstractType()) {
2N/A throw
2N/A new ServiceLocationException(
2N/A ServiceLocationException.PARSE_ERROR,
2N/A "v1_abstract_type",
2N/A new Object[0]);
2N/A
2N/A }
2N/A
2N/A // Reject if not a service: type. SLPv1 doesn't handle
2N/A // nonservice: types.
2N/A
2N/A if (!st.isServiceURL()) {
2N/A throw
2N/A new ServiceLocationException(
2N/A ServiceLocationException.PARSE_ERROR,
2N/A "v1_not_surl",
2N/A new Object[0]);
2N/A
2N/A }
2N/A
2N/A return type;
2N/A }
2N/A
2N/A //
2N/A // Parsing Utilities.
2N/A //
2N/A
2N/A // Parse string, bump byte count.
2N/A
2N/A byte[] getString(StringBuffer buf, DataInputStream dis)
2N/A throws ServiceLocationException, IOException {
2N/A
2N/A int i, n = 0;
2N/A
2N/A // Get length.
2N/A
2N/A n = getInteger(dis);
2N/A
2N/A byte[] bytes = new byte[n];
2N/A
2N/A // Read bytes.
2N/A
2N/A dis.readFully(bytes, 0, n);
2N/A
2N/A // If the encoding type is Unicode, then figure out first
2N/A // whether it's big or little endian from byte header. Future
2N/A // calls won't have to go through this grief unless the byte header
2N/A // is missing.
2N/A
2N/A if (this.charCode == IANACharCode.UNICODE) {
2N/A
2N/A this.charCode = IANACharCode.getUnicodeEndianess(bytes);
2N/A
2N/A }
2N/A
2N/A String charCode = this.charCode;
2N/A
2N/A // If we are still just Unicode by this point, then we need to
2N/A // add the big endian bytes to the beginning of the array.
2N/A // Otherwise, Java won't parse it. Note that we don't change
2N/A // the flag in the header, since we will need to convert the
2N/A // next time around as well.
2N/A
2N/A if (charCode == IANACharCode.UNICODE) {
2N/A charCode = IANACharCode.UNICODE_BIG;
2N/A
2N/A bytes = IANACharCode.addBigEndianFlag(bytes);
2N/A
2N/A }
2N/A
2N/A // Convert the bytes into a string.
2N/A
2N/A buf.setLength(0);
2N/A
2N/A buf.append(getBytesString(bytes, charCode));
2N/A
2N/A return bytes;
2N/A }
2N/A
2N/A // Parse out string, bump byte count. Use header encoding.
2N/A
2N/A byte[] putString(String string, ByteArrayOutputStream baos) {
2N/A
2N/A // If the charCode is UNICODE, arbirtarily change to big or little,
2N/A // while Java will parse.
2N/A
2N/A if (charCode == IANACharCode.UNICODE) {
2N/A charCode = IANACharCode.UNICODE_BIG;
2N/A
2N/A }
2N/A
2N/A byte[] bytes = putStringField(string, baos, charCode);
2N/A
2N/A nbytes += bytes.length;
2N/A
2N/A return bytes;
2N/A
2N/A }
2N/A
2N/A // Parse in a service URL including lifetime if necessary.
2N/A
2N/A protected ServiceURL
2N/A parseServiceURLIn(DataInputStream dis,
2N/A boolean lifeTimeToo,
2N/A short errCode)
2N/A throws ServiceLocationException, IOException {
2N/A
2N/A int lifetime = 0;
2N/A StringBuffer buf = new StringBuffer();
2N/A
2N/A if (lifeTimeToo) {
2N/A lifetime = getInt(dis);
2N/A }
2N/A
2N/A getString(buf, dis);
2N/A
2N/A ServiceURL url = null;
2N/A
2N/A try {
2N/A
2N/A url = new ServiceURLV1(buf.toString(), lifetime);
2N/A
2N/A } catch (IllegalArgumentException ex) {
2N/A
2N/A throw
2N/A new ServiceLocationException(errCode,
2N/A "malformed_url",
2N/A new Object[] {ex});
2N/A }
2N/A
2N/A return url;
2N/A }
2N/A
2N/A // Parse out a service URL including lifetime if required.
2N/A
2N/A void
2N/A parseServiceURLOut(ServiceURL surl,
2N/A boolean lifetimeToo,
2N/A ByteArrayOutputStream baos)
2N/A throws ServiceLocationException {
2N/A
2N/A String ssurl = surl.toString();
2N/A
2N/A if (lifetimeToo) {
2N/A putInt(surl.getLifetime(), baos);
2N/A }
2N/A
2N/A putString(ssurl, baos);
2N/A
2N/A }
2N/A
2N/A // Parse in a list of attributes, returing a vector of
2N/A // ServiceLocationAttribute objects.
2N/A
2N/A protected Vector parseAttributeVectorIn(DataInputStream dis)
2N/A throws ServiceLocationException, IOException {
2N/A
2N/A StringBuffer buf = new StringBuffer();
2N/A
2N/A getString(buf, dis);
2N/A
2N/A SLPConfig config = SLPConfig.getSLPConfig();
2N/A
2N/A // Parse the list into ServiceLocationAttribute objects.
2N/A
2N/A Vector attrForms = parseCommaSeparatedListIn(buf.toString(), false);
2N/A
2N/A int i, n = attrForms.size();
2N/A
2N/A for (i = 0; i < n; i++) {
2N/A String attrForm =
2N/A (String)attrForms.elementAt(i);
2N/A
2N/A attrForms.setElementAt(new ServiceLocationAttributeV1(attrForm,
2N/A charCode,
2N/A false),
2N/A i);
2N/A }
2N/A
2N/A return attrForms;
2N/A }
2N/A
2N/A // Parse out a V1 attribute vector.
2N/A
2N/A void
2N/A parseAttributeVectorOut(Vector attrs,
2N/A ByteArrayOutputStream baos)
2N/A throws ServiceLocationException {
2N/A
2N/A Enumeration en = attrs.elements();
2N/A Vector strings = new Vector();
2N/A
2N/A // Convert the attributes to strings, escaping characters to
2N/A // escape.
2N/A
2N/A while (en.hasMoreElements()) {
2N/A ServiceLocationAttribute attr =
2N/A (ServiceLocationAttribute)en.nextElement();
2N/A
2N/A // Make an SLPv1 attribute out of it, so we can
2N/A // externalize it with the v1 encoding scheme.
2N/A
2N/A ServiceLocationAttributeV1 attrv1 =
2N/A new ServiceLocationAttributeV1(attr);
2N/A attrv1.charCode = charCode;
2N/A String out = attrv1.externalize();
2N/A
2N/A strings.addElement(out);
2N/A
2N/A }
2N/A
2N/A // Parse it out.
2N/A
2N/A parseCommaSeparatedListOut(strings, baos);
2N/A
2N/A }
2N/A
2N/A // Parse in previous responders.
2N/A
2N/A void parsePreviousRespondersIn(DataInputStream dis)
2N/A throws ServiceLocationException, IOException {
2N/A
2N/A StringBuffer buf = new StringBuffer();
2N/A
2N/A getString(buf, dis);
2N/A
2N/A previousResponders =
2N/A parseCommaSeparatedListIn(buf.toString(), true);
2N/A
2N/A }
2N/A
2N/A // Put out a vector of strings.
2N/A
2N/A void putStringVector(Vector v, ByteArrayOutputStream baos) {
2N/A
2N/A int i, n = v.size();
2N/A
2N/A // Put out the total number of strings.
2N/A
2N/A putInt(n, baos);
2N/A
2N/A // Put out the strings.
2N/A
2N/A for (i = 0; i < n; i++) {
2N/A
2N/A putString((String)v.elementAt(i), baos);
2N/A }
2N/A }
2N/A
2N/A // Return an SLPv1 DAAdvert.
2N/A
2N/A SDAAdvert
2N/A getDAAdvert(short xid,
2N/A long timestamp,
2N/A ServiceURL url,
2N/A Vector scopes,
2N/A Vector attrs)
2N/A throws ServiceLocationException {
2N/A
2N/A // If scopes vector is null, then return all scopes for this
2N/A // DA.
2N/A
2N/A if (scopes.size() <= 0) {
2N/A scopes = SLPConfig.getSLPConfig().getSAConfiguredScopes();
2N/A
2N/A }
2N/A
2N/A return new SLPV1SDAAdvert(this, xid, timestamp, url, scopes, attrs);
2N/A
2N/A }
2N/A
2N/A // Reimplement clone() to get the header size right.
2N/A
2N/A public Object clone()
2N/A throws CloneNotSupportedException {
2N/A SLPHeaderV1 hdr = (SLPHeaderV1)super.clone();
2N/A
2N/A hdr.nbytes = HEADER_BYTES + 2; // for error code...
2N/A
2N/A return hdr;
2N/A }
2N/A}