xref: /onnv-gate/usr/src/lib/libslp/javalib/com/sun/slp/SLPConfig.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 1999-2003 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 //  SLPConfig.java
280Sstevel@tonic-gate //
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /**
310Sstevel@tonic-gate  * This class is a singleton - it has the configuration which
320Sstevel@tonic-gate  * is the default.  It reads from a configuration file and
330Sstevel@tonic-gate  * this overrides the default.  If the config file does not
340Sstevel@tonic-gate  * expressly forbid it, the ServiceLocationManager interface
350Sstevel@tonic-gate  * allows some of these configuration options to be modified.
360Sstevel@tonic-gate  * This configuration is refered to by many points of the
370Sstevel@tonic-gate  * implementation. Note that the class itself is abstract,
380Sstevel@tonic-gate  * and is extended by two classes, one that allows slpd to
390Sstevel@tonic-gate  * run as an SA server only, the other allows it to run
400Sstevel@tonic-gate  * as a DA as well.
410Sstevel@tonic-gate  *
420Sstevel@tonic-gate  * @see com.sun.slp.ServiceLocationManager
430Sstevel@tonic-gate  */
440Sstevel@tonic-gate 
450Sstevel@tonic-gate package com.sun.slp;
460Sstevel@tonic-gate 
470Sstevel@tonic-gate import java.net.*;
480Sstevel@tonic-gate import java.util.*;
490Sstevel@tonic-gate import java.text.*;
500Sstevel@tonic-gate import java.io.*;
510Sstevel@tonic-gate 
520Sstevel@tonic-gate /*
530Sstevel@tonic-gate  * This class contains all configuration information.  It
540Sstevel@tonic-gate  * is hard coded to know the defaults, and will read a config
550Sstevel@tonic-gate  * file if it is present.  The config file will override the
560Sstevel@tonic-gate  * default values and policy.  If the config file allows it
570Sstevel@tonic-gate  * the user may reset some of these values using the
580Sstevel@tonic-gate  * ServiceLocationManager interface.
590Sstevel@tonic-gate  *
600Sstevel@tonic-gate  */
610Sstevel@tonic-gate class SLPConfig {
620Sstevel@tonic-gate 
630Sstevel@tonic-gate     /**
640Sstevel@tonic-gate      * A Java properties file defines `\' as an escape character, which
650Sstevel@tonic-gate      * conflicts with the SLP API escape convention. Therefore, we need
660Sstevel@tonic-gate      * to subclass properties so we can parse in the file ourselves.
670Sstevel@tonic-gate      */
680Sstevel@tonic-gate 
690Sstevel@tonic-gate     public static class SLPProperties extends Properties {
700Sstevel@tonic-gate 
SLPProperties(Properties p)710Sstevel@tonic-gate 	SLPProperties(Properties p) {
720Sstevel@tonic-gate 	    super(p);
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 	}
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	// Parse the SLP properties file ourselves. Groan! We don't recognize
770Sstevel@tonic-gate 	//  backslash as an escape.
780Sstevel@tonic-gate 
load(InputStream in)790Sstevel@tonic-gate 	public synchronized void load(InputStream in) throws IOException {
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 	    BufferedReader rd = new BufferedReader(new InputStreamReader(in));
820Sstevel@tonic-gate 
830Sstevel@tonic-gate 	    while (rd.ready()) {
840Sstevel@tonic-gate 		String ln = rd.readLine();
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 		// Throw out anything that begins with '#' or ';'.
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 		if (ln.startsWith("#") ||
890Sstevel@tonic-gate 		    ln.startsWith(";") ||
900Sstevel@tonic-gate 		    ln.length() <= 0) {
910Sstevel@tonic-gate 		    continue;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 		}
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 		// Parse out equals sign, if any. Note that we trim any
960Sstevel@tonic-gate 		//  white space preceding or following data strings.
970Sstevel@tonic-gate 		//  Although the grammar doesn't allow it, users may
980Sstevel@tonic-gate 		//  enter blanks in their configuration files.
990Sstevel@tonic-gate 		// NOTE:  White space is not allowed in the data of
1000Sstevel@tonic-gate 		//  property tag or values.  If included, according
1010Sstevel@tonic-gate 		//  to RFC 2614, Section 2.1 these MUST be escaped,
1020Sstevel@tonic-gate 		//  ie. space would be represented with '\20'.
1030Sstevel@tonic-gate 		//  Therefore, it is *completely* safe to perform
1040Sstevel@tonic-gate 		//  these trim()s.  They will catch errors resulting
1050Sstevel@tonic-gate 		//  from sloppy data entry in slp.conf files and
1060Sstevel@tonic-gate 		//  never corrupt or alter correctly formatted
1070Sstevel@tonic-gate 		//  properties.
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 		SLPTokenizer tk = new SLPTokenizer(ln, "=");
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 		if (!tk.hasMoreTokens()) {// empty line...
1120Sstevel@tonic-gate 		    continue;
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 		}
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 		String prop = tk.nextToken().trim();
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 		if (prop.trim().length() <= 0) {// line has just spaces...
1190Sstevel@tonic-gate 		    continue;
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 		}
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 		if (!tk.hasMoreTokens()) {// line has no definition...
1240Sstevel@tonic-gate 		    continue;
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 		}
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 		// Register the property.
1290Sstevel@tonic-gate 		String def = tk.nextToken().trim();
1300Sstevel@tonic-gate 		this.setProperty(prop, def);
1310Sstevel@tonic-gate 	    }
1320Sstevel@tonic-gate 	}
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate     }
1350Sstevel@tonic-gate 
SLPConfig()1360Sstevel@tonic-gate     protected SLPConfig() {
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	// Create a temporary, default log to report any errors during
1390Sstevel@tonic-gate 	//  configuration.
1400Sstevel@tonic-gate 	log = new StderrLog();
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	// Initialize properties. Properties on command line override config
1430Sstevel@tonic-gate 	//  file properties, and both override defaults.
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	Properties sysProps = (Properties)(System.getProperties().clone());
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	// Load Defalts.
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	try {
1500Sstevel@tonic-gate 	    Class.forName("com.sun.slp.Defaults");
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 	} catch (ClassNotFoundException ex) {
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	    Assert.printMessageAndDie(this,
1550Sstevel@tonic-gate 				      "no_class",
1560Sstevel@tonic-gate 				      new Object[] {"com.sun.slp.Defaults"});
1570Sstevel@tonic-gate 	}
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	// System properties now contain Defaults
1600Sstevel@tonic-gate 	Properties defaultProps = System.getProperties();
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	// Load config file.
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	SLPProperties slpProps = new SLPProperties(new Properties());
1650Sstevel@tonic-gate 	try {
1660Sstevel@tonic-gate 	    InputStream fis = getConfigURLStream();
1670Sstevel@tonic-gate 	    if (fis != null) {
1680Sstevel@tonic-gate 		slpProps.load(fis);
1690Sstevel@tonic-gate 		System.setProperties(slpProps);
1700Sstevel@tonic-gate 	    }
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 	} catch (IOException ex) {
1730Sstevel@tonic-gate 	    writeLog("unparsable_config_file",
1740Sstevel@tonic-gate 		     new Object[] {ex.getMessage()});
1750Sstevel@tonic-gate 	}
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	// Add config properties to Defaults, overwritting any pre-existing
1780Sstevel@tonic-gate 	//  entries
1790Sstevel@tonic-gate 	defaultProps.putAll(slpProps);
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	// Now add in system props, overwritting any pre-existing entries
1820Sstevel@tonic-gate 	defaultProps.putAll(sysProps);
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	System.setProperties(defaultProps);
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	// Initialize useScopes property. This is read-only after the file
1880Sstevel@tonic-gate 	//  has been loaded.
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	configuredScopes = initializeScopes("net.slp.useScopes");
1910Sstevel@tonic-gate 	saConfiguredScopes = (Vector)configuredScopes.clone();
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	// Add default scope to scopes for SA.
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 	if (saConfiguredScopes.size() <= 0) {
1960Sstevel@tonic-gate 	    saConfiguredScopes.addElement(Defaults.DEFAULT_SCOPE);
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	}
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	// Initialize SA scopes. This uses a Sun specific property for
2010Sstevel@tonic-gate 	//  scopes only used by the SA and adds in the DA scopes.
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 	saOnlyScopes = initializeScopes(DATable.SA_ONLY_SCOPES_PROP);
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	// Initialized preconfigured DAs.
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	preconfiguredDAs = initializePreconfiguredDAs();
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	// Initialize broadcast flag.
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	broadcastOnly = Boolean.getBoolean("net.slp.isBroadcastOnly");
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	// Initialize logging. Default is stderr, first check for alternate.
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	String failed = null;
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 	try {
2180Sstevel@tonic-gate 	    String loggerClassName =
2190Sstevel@tonic-gate 		System.getProperty("sun.net.slp.loggerClass");
2200Sstevel@tonic-gate 	    if (loggerClassName != null) {
2210Sstevel@tonic-gate 		Class loggerClass = Class.forName(loggerClassName);
2220Sstevel@tonic-gate 		// Protect against disastrous pilot error, such as trying
2230Sstevel@tonic-gate 		// to use com.sun.slp.SLPConfig as the log class
2240Sstevel@tonic-gate 		// (causes stack recursion)
2250Sstevel@tonic-gate 		if (Class.forName("java.io.Writer").isAssignableFrom(
2260Sstevel@tonic-gate 							loggerClass)) {
2270Sstevel@tonic-gate 		    Object logger = loggerClass.newInstance();
2280Sstevel@tonic-gate 		    log = (Writer) logger;
2290Sstevel@tonic-gate 		} else {
2300Sstevel@tonic-gate 		    failed = formatMessage(
2310Sstevel@tonic-gate 					   "bad_log_class",
2320Sstevel@tonic-gate 					   new Object[] {
2330Sstevel@tonic-gate 			loggerClass.toString()}) + "\n";
2340Sstevel@tonic-gate 		}
2350Sstevel@tonic-gate 	    }
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	} catch (Throwable ex) {
2380Sstevel@tonic-gate 	    log = null;
2390Sstevel@tonic-gate 	    failed = formatMessage(
2400Sstevel@tonic-gate 				   "bad_log",
2410Sstevel@tonic-gate 				   new Object[] {
2420Sstevel@tonic-gate 		ex.toString()}) + "\n";
2430Sstevel@tonic-gate 	}
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	// If no alternate log, revert to minimal default
2460Sstevel@tonic-gate 	if (log == null) {
2470Sstevel@tonic-gate 	    log = new StderrLog();
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	    // If the alternate log failed, log it through the default log
2500Sstevel@tonic-gate 	    if (failed != null) {
2510Sstevel@tonic-gate 		try {
2520Sstevel@tonic-gate 		    synchronized (log) {
2530Sstevel@tonic-gate 			log.write(failed);
2540Sstevel@tonic-gate 			log.flush();
2550Sstevel@tonic-gate 		    }
2560Sstevel@tonic-gate 		} catch (IOException giveUp) {}
2570Sstevel@tonic-gate 	    }
2580Sstevel@tonic-gate 	}
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate     }
2610Sstevel@tonic-gate 
getConfigURLStream()2620Sstevel@tonic-gate     private InputStream getConfigURLStream() {
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	// Open a URL onto the configuration file.
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	String conf = System.getProperty("sun.net.slp.configURL");
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	if (conf == null) {
2690Sstevel@tonic-gate 	    conf = Defaults.SOLARIS_CONF;
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 	}
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 	InputStream str = null;
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	try {
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	    URL confURL = new URL(conf);
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 	    str = confURL.openStream();
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 	} catch (MalformedURLException ex) {
2820Sstevel@tonic-gate 	    writeLog("url_malformed",
2830Sstevel@tonic-gate 		     new Object[] {conf});
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	} catch (IOException ex) {
2860Sstevel@tonic-gate 	    if (conf != Defaults.SOLARIS_CONF) {
2870Sstevel@tonic-gate 		// don't complain if we can't find our own default
2880Sstevel@tonic-gate 		writeLog("unparsable_config_file",
2890Sstevel@tonic-gate 			 new Object[] {ex.getMessage()});
2900Sstevel@tonic-gate 	    }
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	}
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	return str;
2950Sstevel@tonic-gate     }
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate     // ------------------------------------------------------------
2980Sstevel@tonic-gate     // Property manipulation functions
2990Sstevel@tonic-gate     //
3000Sstevel@tonic-gate 
OKBound(int i, int lb, int ub)3010Sstevel@tonic-gate     private boolean OKBound(int i, int lb, int ub) {
3020Sstevel@tonic-gate 	if (i < lb || i > ub)
3030Sstevel@tonic-gate 	    return false;
3040Sstevel@tonic-gate 	else
3050Sstevel@tonic-gate 	    return true;
3060Sstevel@tonic-gate     }
3070Sstevel@tonic-gate 
getIntProperty(String prop, int df, int lb, int ub)3080Sstevel@tonic-gate     int getIntProperty(String prop, int df, int lb, int ub) {
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	int i = Integer.getInteger(prop, df).intValue();
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	if (OKBound(i, lb, ub)) {
3130Sstevel@tonic-gate 	    return i;
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	} else {
3160Sstevel@tonic-gate 	    writeLog("bad_prop_tag", new Object[] {prop});
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	    return df;
3190Sstevel@tonic-gate 	}
3200Sstevel@tonic-gate     }
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate     // ------------------------------------------------------------
3230Sstevel@tonic-gate     // Multicast radius
3240Sstevel@tonic-gate     //
3250Sstevel@tonic-gate     private int iMinMCRadius = 1;   // link local scope
3260Sstevel@tonic-gate     private int iMaxMCRadius = 255; // universal scope
3270Sstevel@tonic-gate 
getMCRadius()3280Sstevel@tonic-gate     int getMCRadius() {
3290Sstevel@tonic-gate 	return getIntProperty("net.slp.multicastTTL",
3300Sstevel@tonic-gate 			      Defaults.iMulticastRadius,
3310Sstevel@tonic-gate 			      iMinMCRadius,
3320Sstevel@tonic-gate 			      iMaxMCRadius);
3330Sstevel@tonic-gate     }
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate     // ------------------------------------------------------------
3360Sstevel@tonic-gate     // Heartbeat interval, seconds.
3370Sstevel@tonic-gate     //
3380Sstevel@tonic-gate     private final int iMinHeart = 2000;    // 10 minutes
3390Sstevel@tonic-gate     private final int iMaxHeart = 259200000; // 3 days
3400Sstevel@tonic-gate 
getAdvertHeartbeatTime()3410Sstevel@tonic-gate     int getAdvertHeartbeatTime() {
3420Sstevel@tonic-gate 	return getIntProperty("net.slp.DAHeartBeat",
3430Sstevel@tonic-gate 			      Defaults.iHeartbeat,
3440Sstevel@tonic-gate 			      iMinHeart,
3450Sstevel@tonic-gate 			      iMaxHeart);
3460Sstevel@tonic-gate     }
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate     // ------------------------------------------------------------
3490Sstevel@tonic-gate     // Active discovery interval, seconds.
3500Sstevel@tonic-gate     //
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate     private final int iMinDisc = 300;    // 5 minutes
3530Sstevel@tonic-gate     private final int iMaxDisc = 10800;  // 3 hours
3540Sstevel@tonic-gate 
getActiveDiscoveryInterval()3550Sstevel@tonic-gate     int getActiveDiscoveryInterval() {
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	// We allow zero in order to turn active discovery off, but
3580Sstevel@tonic-gate 	//  if 5 minutes is the smallest actual time.
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	int prop = getIntProperty("net.slp.DAActiveDiscoveryInterval",
3610Sstevel@tonic-gate 				  Defaults.iActiveDiscoveryInterval,
3620Sstevel@tonic-gate 				  0,
3630Sstevel@tonic-gate 				  iMaxDisc);
3640Sstevel@tonic-gate 	if (prop > 0 && prop < iMinDisc) {
3650Sstevel@tonic-gate 	    writeLog("bad_prop_tag",
3660Sstevel@tonic-gate 		     new Object[] {"net.slp.DAActiveDiscoveryInterval"});
3670Sstevel@tonic-gate 	    return iMinDisc;
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	}
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 	return prop;
3720Sstevel@tonic-gate     }
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate     // ------------------------------------------------------------
3760Sstevel@tonic-gate     // Active discovery granularity, seconds.
3770Sstevel@tonic-gate     //
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate     private int iMaxDiscGran = iMaxDisc * 2;
3800Sstevel@tonic-gate 
getActiveDiscoveryGranularity()3810Sstevel@tonic-gate     int getActiveDiscoveryGranularity() {
3820Sstevel@tonic-gate 	return getIntProperty("sun.net.slp.DAActiveDiscoveryGranularity",
3830Sstevel@tonic-gate 			      Defaults.iActiveDiscoveryGranularity,
3840Sstevel@tonic-gate 			      0,
3850Sstevel@tonic-gate 			      iMaxDiscGran);
3860Sstevel@tonic-gate     }
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate     // ------------------------------------------------------------
3890Sstevel@tonic-gate     // Bound for random wait, milliseconds.
3900Sstevel@tonic-gate     //
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate     private final int iMinWait = 1000;  // 1 sec.
3930Sstevel@tonic-gate     private final int iMaxWait = 3000;  // 3 sec.
3940Sstevel@tonic-gate 
getRandomWaitBound()3950Sstevel@tonic-gate     int getRandomWaitBound() {
3960Sstevel@tonic-gate 	return getIntProperty("net.slp.randomWaitBound",
3970Sstevel@tonic-gate 			      Defaults.iRandomWaitBound,
3980Sstevel@tonic-gate 			      iMinWait,
3990Sstevel@tonic-gate 			      iMaxWait);
4000Sstevel@tonic-gate     }
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate     private static Random randomWait = null;
4030Sstevel@tonic-gate 
getRandomWait()4040Sstevel@tonic-gate     long getRandomWait() {
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	if (randomWait == null) {
4070Sstevel@tonic-gate 	    randomWait = new Random();
4080Sstevel@tonic-gate 	}
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	double r = randomWait.nextDouble();
4110Sstevel@tonic-gate 	double max = (double)getRandomWaitBound();
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate 	return (long)(max * r);
4140Sstevel@tonic-gate     }
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate     // ------------------------------------------------------------
4170Sstevel@tonic-gate     // TCP timeout, milliseconds.
4180Sstevel@tonic-gate     //
4190Sstevel@tonic-gate     final static private int iMinTimeout = 100;
4200Sstevel@tonic-gate     final static private int iMaxTimeout = 360000;
4210Sstevel@tonic-gate 
getTCPTimeout()4220Sstevel@tonic-gate     int getTCPTimeout() {
4230Sstevel@tonic-gate 	return getIntProperty("sun.net.slp.TCPTimeout",
4240Sstevel@tonic-gate 			      Defaults.iTCPTimeout,
4250Sstevel@tonic-gate 			      iMinTimeout,
4260Sstevel@tonic-gate 			      iMaxTimeout);
4270Sstevel@tonic-gate     }
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate     // ------------------------------------------------------------
4300Sstevel@tonic-gate     //  Path MTU
4310Sstevel@tonic-gate     //
4320Sstevel@tonic-gate     private final int iMinMTU = 128; // used for some ppp connections
4330Sstevel@tonic-gate     private final int iMaxMTU = 8192; // used on some LANs
4340Sstevel@tonic-gate 
getMTU()4350Sstevel@tonic-gate     int getMTU() {
4360Sstevel@tonic-gate 	return getIntProperty("net.slp.MTU",
4370Sstevel@tonic-gate 			      Defaults.iMTU,
4380Sstevel@tonic-gate 			      iMinMTU,
4390Sstevel@tonic-gate 			      iMaxMTU);
4400Sstevel@tonic-gate     }
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate     // ------------------------------------------------------------
4440Sstevel@tonic-gate     // Serialized registrations.
4450Sstevel@tonic-gate     //
4460Sstevel@tonic-gate 
getSerializedRegURL()4470Sstevel@tonic-gate     String getSerializedRegURL() {
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 	return System.getProperty("net.slp.serializedRegURL", null);
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate     }
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate     // ------------------------------------------------------------
4540Sstevel@tonic-gate     // Are we running as a DA or SA server?
4550Sstevel@tonic-gate     //
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate     protected static boolean isSA = false;
4580Sstevel@tonic-gate 
isDA()4590Sstevel@tonic-gate     boolean isDA() {
4600Sstevel@tonic-gate 	return false;
4610Sstevel@tonic-gate     }
4620Sstevel@tonic-gate 
isSA()4630Sstevel@tonic-gate     boolean isSA() {
4640Sstevel@tonic-gate 	return isSA;
4650Sstevel@tonic-gate     }
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate     // ------------------------------------------------------------
4680Sstevel@tonic-gate     // DA and SA attributes
4690Sstevel@tonic-gate     //
4700Sstevel@tonic-gate 
getDAAttributes()4710Sstevel@tonic-gate     Vector getDAAttributes() {
4720Sstevel@tonic-gate 	return getAttributes("net.slp.DAAttributes",
4730Sstevel@tonic-gate 			     Defaults.defaultDAAttributes,
4740Sstevel@tonic-gate 			     true);
4750Sstevel@tonic-gate     }
4760Sstevel@tonic-gate 
getSAAttributes()4770Sstevel@tonic-gate     Vector getSAAttributes() {
4780Sstevel@tonic-gate 	return getAttributes("net.slp.SAAttributes",
4790Sstevel@tonic-gate 			     Defaults.defaultSAAttributes,
4800Sstevel@tonic-gate 			     false);
4810Sstevel@tonic-gate     }
4820Sstevel@tonic-gate 
getAttributes(String prop, Vector defaults, boolean daAttrs)4830Sstevel@tonic-gate     private Vector getAttributes(String prop,
4840Sstevel@tonic-gate 				 Vector defaults,
4850Sstevel@tonic-gate 				 boolean daAttrs) {
4860Sstevel@tonic-gate 	String attrList =
4870Sstevel@tonic-gate 	    System.getProperty(prop);
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 	if (attrList == null || attrList.length() <= 0) {
4900Sstevel@tonic-gate 	    return (Vector)defaults.clone();
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	}
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	try {
4950Sstevel@tonic-gate 	    Vector sAttrs =
4960Sstevel@tonic-gate 		SrvLocHeader.parseCommaSeparatedListIn(attrList, false);
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate 	    Vector attrs = new Vector();
4990Sstevel@tonic-gate 	    int i, n = sAttrs.size();
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 	    // Create attribute objects.
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 	    for (i = 0; i < n; i++) {
5040Sstevel@tonic-gate 		String attrExp = (String)sAttrs.elementAt(i);
5050Sstevel@tonic-gate 		ServiceLocationAttribute attr =
5060Sstevel@tonic-gate 		    new ServiceLocationAttribute(attrExp, false);
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 		// If this is the min-refresh-interval, then check the value.
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate 		if (daAttrs &&
5110Sstevel@tonic-gate 		    attr.getId().equals(
5120Sstevel@tonic-gate 				Defaults.MIN_REFRESH_INTERVAL_ATTR_ID)) {
5130Sstevel@tonic-gate 		    Vector values = attr.getValues();
5140Sstevel@tonic-gate 		    boolean errorp = true;
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 		    if (values != null && values.size() == 1) {
5170Sstevel@tonic-gate 			Object val = values.elementAt(0);
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 			if (val instanceof Integer) {
5200Sstevel@tonic-gate 			    int ival = ((Integer)val).intValue();
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 			    if (ival >= 0 &&
5230Sstevel@tonic-gate 				ival <= ServiceURL.LIFETIME_MAXIMUM) {
5240Sstevel@tonic-gate 				errorp = false;
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 			    }
5270Sstevel@tonic-gate 			}
5280Sstevel@tonic-gate 		    }
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 		    // Throw exception if it didn't work.
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 		    if (errorp) {
5330Sstevel@tonic-gate 			throw new ServiceLocationException(
5340Sstevel@tonic-gate 				ServiceLocationException.PARSE_ERROR,
5350Sstevel@tonic-gate 				"syntax_error_prop",
5360Sstevel@tonic-gate 				new Object[] {prop, attrs});
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate 		    }
5390Sstevel@tonic-gate 		}
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 		// Add attribute to vector.
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 		attrs.addElement(attr);
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate 	    }
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	    return attrs;
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate 	} catch (Exception ex) {
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	    writeLog("syntax_error_prop",
5520Sstevel@tonic-gate 		     new Object[] {prop, attrList});
5530Sstevel@tonic-gate 	    return (Vector)defaults.clone();
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	}
5560Sstevel@tonic-gate     }
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate     // -------------------------------------------------------------
5590Sstevel@tonic-gate     // Do we support V1?
5600Sstevel@tonic-gate     //
5610Sstevel@tonic-gate 
isV1Supported()5620Sstevel@tonic-gate     boolean isV1Supported() {
5630Sstevel@tonic-gate 	return false;
5640Sstevel@tonic-gate     }
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate     // -------------------------------------------------------------
5670Sstevel@tonic-gate     // Queue length for server socket.
5680Sstevel@tonic-gate     //
5690Sstevel@tonic-gate 
getServerSocketQueueLength()5700Sstevel@tonic-gate     int getServerSocketQueueLength() {
5710Sstevel@tonic-gate 	return getIntProperty("sun.net.slp.serverSocketQueueLength",
5720Sstevel@tonic-gate 			      Defaults.iSocketQueueLength,
5730Sstevel@tonic-gate 			      0,
5740Sstevel@tonic-gate 			      Integer.MAX_VALUE);
5750Sstevel@tonic-gate     }
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate     // ------------------------------------------------------------
5780Sstevel@tonic-gate     // Testing options
5790Sstevel@tonic-gate     //
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 
traceAll()5820Sstevel@tonic-gate     boolean traceAll() {// not official!
5830Sstevel@tonic-gate 	return Boolean.getBoolean("sun.net.slp.traceALL");
5840Sstevel@tonic-gate     }
5850Sstevel@tonic-gate 
regTest()5860Sstevel@tonic-gate     boolean regTest() {
5870Sstevel@tonic-gate 	if (Boolean.getBoolean("sun.net.slp.traceALL") ||
5880Sstevel@tonic-gate 	    Boolean.getBoolean("net.slp.traceReg"))
5890Sstevel@tonic-gate 	    return true;
5900Sstevel@tonic-gate 	else
5910Sstevel@tonic-gate 	    return false;
5920Sstevel@tonic-gate     }
5930Sstevel@tonic-gate 
traceMsg()5940Sstevel@tonic-gate     boolean traceMsg() {
5950Sstevel@tonic-gate 	if (Boolean.getBoolean("sun.net.slp.traceALL") ||
5960Sstevel@tonic-gate 	    Boolean.getBoolean("net.slp.traceMsg"))
5970Sstevel@tonic-gate 	    return true;
5980Sstevel@tonic-gate 	else
5990Sstevel@tonic-gate 	    return false;
6000Sstevel@tonic-gate     }
6010Sstevel@tonic-gate 
traceDrop()6020Sstevel@tonic-gate     boolean traceDrop() {
6030Sstevel@tonic-gate 	if (Boolean.getBoolean("sun.net.slp.traceALL") ||
6040Sstevel@tonic-gate 	    Boolean.getBoolean("net.slp.traceDrop"))
6050Sstevel@tonic-gate 	    return true;
6060Sstevel@tonic-gate 	else
6070Sstevel@tonic-gate 	    return false;
6080Sstevel@tonic-gate     }
6090Sstevel@tonic-gate 
traceDATraffic()6100Sstevel@tonic-gate     boolean traceDATraffic() {
6110Sstevel@tonic-gate 	if (Boolean.getBoolean("sun.net.slp.traceALL") ||
6120Sstevel@tonic-gate 	    Boolean.getBoolean("net.slp.traceDATraffic"))
6130Sstevel@tonic-gate 	    return true;
6140Sstevel@tonic-gate 	else
6150Sstevel@tonic-gate 	    return false;
6160Sstevel@tonic-gate     }
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate     // cannot use Boolean.getBoolean as the default is 'true'
6190Sstevel@tonic-gate     // using that mechanism, absense would be considered 'false'
6200Sstevel@tonic-gate 
passiveDADetection()6210Sstevel@tonic-gate     boolean passiveDADetection() {
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 	String sPassive =
6240Sstevel@tonic-gate 	    System.getProperty("net.slp.passiveDADetection", "true");
6250Sstevel@tonic-gate 	if (sPassive.equalsIgnoreCase("true"))
6260Sstevel@tonic-gate 	    return true;
6270Sstevel@tonic-gate 	else
6280Sstevel@tonic-gate 	    return false;
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate     }
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate     // Initialized when the SLPConfig object is created to avoid changing
6330Sstevel@tonic-gate     //  during the program.
6340Sstevel@tonic-gate     private boolean broadcastOnly = false;
6350Sstevel@tonic-gate 
isBroadcastOnly()6360Sstevel@tonic-gate     boolean isBroadcastOnly() {
6370Sstevel@tonic-gate 	return broadcastOnly;
6380Sstevel@tonic-gate     }
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate     // ------------------------------------------------------------
6420Sstevel@tonic-gate     // Multicast/broadcast socket mangement.
6430Sstevel@tonic-gate     //
6440Sstevel@tonic-gate     DatagramSocket broadSocket = null;   // cached broadcast socket.
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate     // Reopen the multicast/broadcast socket bound to the
6480Sstevel@tonic-gate     //  interface. If groups is not null, then join all
6490Sstevel@tonic-gate     //  the groups. Otherwise, this is send only.
6500Sstevel@tonic-gate 
6510Sstevel@tonic-gate     DatagramSocket
refreshMulticastSocketOnInterface(InetAddress interfac, Vector groups)6520Sstevel@tonic-gate 	refreshMulticastSocketOnInterface(InetAddress interfac,
6530Sstevel@tonic-gate 					  Vector groups) {
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 	try {
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate 	    // Reopen it.
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate 	    DatagramSocket dss =
6600Sstevel@tonic-gate 		getMulticastSocketOnInterface(interfac,
6610Sstevel@tonic-gate 					      (groups == null ? true:false));
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 	    if ((groups != null) && (dss instanceof MulticastSocket)) {
6640Sstevel@tonic-gate 		int i, n = groups.size();
6650Sstevel@tonic-gate 		MulticastSocket mss = (MulticastSocket)dss;
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate 		for (i = 0; i < n; i++) {
6680Sstevel@tonic-gate 		    InetAddress maddr = (InetAddress)groups.elementAt(i);
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate 		    mss.joinGroup(maddr);
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate 		}
6730Sstevel@tonic-gate 	    }
6740Sstevel@tonic-gate 
6750Sstevel@tonic-gate 	    return dss;
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate 	} catch (Exception ex) {
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate 	    // Any exception in error recovery causes program to die.
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate 	    Assert.slpassert(false,
6820Sstevel@tonic-gate 			  "cast_socket_failure",
6830Sstevel@tonic-gate 			  new Object[] {ex, ex.getMessage()});
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate 	}
6860Sstevel@tonic-gate 
6870Sstevel@tonic-gate 	return null;
6880Sstevel@tonic-gate     }
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate     // Open a multicast/broadcast socket on the interface. Note that if
6910Sstevel@tonic-gate     //  the socket is broadcast, the network interface is not specified in the
6920Sstevel@tonic-gate     //  creation message. Is it bound to all interfaces? The isSend parameter
6930Sstevel@tonic-gate     //  specifies whether the socket is for send only.
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate     DatagramSocket
getMulticastSocketOnInterface(InetAddress interfac, boolean isSend)6960Sstevel@tonic-gate 	getMulticastSocketOnInterface(InetAddress interfac, boolean isSend)
6970Sstevel@tonic-gate 	throws ServiceLocationException {
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate 	DatagramSocket castSocket = null;
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 	// Substitute broadcast if we are configured for it.
7020Sstevel@tonic-gate 
7030Sstevel@tonic-gate 	if (isBroadcastOnly()) {
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 	    try {
7060Sstevel@tonic-gate 
7070Sstevel@tonic-gate 		// If transmit, then simply return a new socket.
7080Sstevel@tonic-gate 
7090Sstevel@tonic-gate 		if (isSend) {
7100Sstevel@tonic-gate 		    castSocket = new DatagramSocket();
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate 		} else {
7130Sstevel@tonic-gate 
7140Sstevel@tonic-gate 		    // Return cached socket if there.
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate 		    if (broadSocket != null) {
7170Sstevel@tonic-gate 			castSocket = broadSocket;
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate 		    } else {
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 			// Make a new broadcast socket.
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate 			castSocket =
7240Sstevel@tonic-gate 			    new DatagramSocket(Defaults.iSLPPort,
7250Sstevel@tonic-gate 					       getBroadcastAddress());
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 		    }
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate 		    // Cache for future reference.
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate 		    broadSocket = castSocket;
7320Sstevel@tonic-gate 		}
7330Sstevel@tonic-gate 	    } catch (SocketException ex) {
7340Sstevel@tonic-gate 		throw
7350Sstevel@tonic-gate 		    new ServiceLocationException(
7360Sstevel@tonic-gate 				ServiceLocationException.NETWORK_INIT_FAILED,
7370Sstevel@tonic-gate 				"socket_creation_failure",
7380Sstevel@tonic-gate 				new Object[] {
7390Sstevel@tonic-gate 			getBroadcastAddress(), ex.getMessage()});
7400Sstevel@tonic-gate 	    }
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate 	} else {
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	    // Create a multicast socket.
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 	    MulticastSocket ms;
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate 	    try {
7490Sstevel@tonic-gate 
7500Sstevel@tonic-gate 		if (isSend) {
7510Sstevel@tonic-gate 		    ms = new MulticastSocket();
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate 		} else {
7540Sstevel@tonic-gate 		    ms = new MulticastSocket(Defaults.iSLPPort);
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 		}
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate 	    } catch (IOException ex) {
7590Sstevel@tonic-gate 		throw
7600Sstevel@tonic-gate 		    new ServiceLocationException(
7610Sstevel@tonic-gate 				ServiceLocationException.NETWORK_INIT_FAILED,
7620Sstevel@tonic-gate 				"socket_creation_failure",
7630Sstevel@tonic-gate 				new Object[] {interfac, ex.getMessage()});
7640Sstevel@tonic-gate 	    }
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 	    try {
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate 		// Set the TTL and the interface on the multicast socket.
7700Sstevel@tonic-gate 		//  Client is responsible for joining group.
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate 		ms.setTimeToLive(getMCRadius());
7730Sstevel@tonic-gate 		ms.setInterface(interfac);
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 	    } catch (IOException ex) {
7760Sstevel@tonic-gate 		throw
7770Sstevel@tonic-gate 		    new ServiceLocationException(
7780Sstevel@tonic-gate 				ServiceLocationException.NETWORK_INIT_FAILED,
7790Sstevel@tonic-gate 				"socket_initializtion_failure",
7800Sstevel@tonic-gate 				new Object[] {interfac, ex.getMessage()});
7810Sstevel@tonic-gate 	    }
7820Sstevel@tonic-gate 
7830Sstevel@tonic-gate 	    castSocket = ms;
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 	}
7860Sstevel@tonic-gate 
7870Sstevel@tonic-gate 	return castSocket;
7880Sstevel@tonic-gate     }
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate     // ------------------------------------------------------------
7910Sstevel@tonic-gate     // Type hint
7920Sstevel@tonic-gate     //
7930Sstevel@tonic-gate 
7940Sstevel@tonic-gate     // Return a vector of ServiceType objects for the type hint.
7950Sstevel@tonic-gate 
getTypeHint()7960Sstevel@tonic-gate     Vector getTypeHint() {
7970Sstevel@tonic-gate 	Vector hint = new Vector();
7980Sstevel@tonic-gate 	String sTypeList = System.getProperty("net.slp.typeHint", "");
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate 	if (sTypeList.length() <= 0) {
8010Sstevel@tonic-gate 	    return hint;
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	}
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate 	// Create a vector of ServiceType objects for the type hint.
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 	try {
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 	    hint = SrvLocHeader.parseCommaSeparatedListIn(sTypeList, true);
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	    int i, n = hint.size();
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 	    for (i = 0; i < n; i++) {
8140Sstevel@tonic-gate 		String type = (String)hint.elementAt(i);
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 		hint.setElementAt(new ServiceType(type), i);
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate 	    }
8190Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate 	    writeLog("syntax_error_prop",
8220Sstevel@tonic-gate 		     new Object[] {"net.slp.typeHint", sTypeList});
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate 	    hint.removeAllElements();
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	}
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 	return hint;
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate     }
8310Sstevel@tonic-gate 
8320Sstevel@tonic-gate     // ------------------------------------------------------------
8330Sstevel@tonic-gate     // Configured scope handling
8340Sstevel@tonic-gate     //
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate     // Vector of configured scopes.
8370Sstevel@tonic-gate 
8380Sstevel@tonic-gate     private Vector configuredScopes = null;
8390Sstevel@tonic-gate 
8400Sstevel@tonic-gate     // Vector of configures scopes for SA.
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate     private Vector saConfiguredScopes = null;
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate     // Vector of scopes only in the sa server.
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate     private Vector saOnlyScopes = null;
8470Sstevel@tonic-gate 
8480Sstevel@tonic-gate     // Return the configured scopes.
8490Sstevel@tonic-gate 
getConfiguredScopes()8500Sstevel@tonic-gate     Vector getConfiguredScopes() {
8510Sstevel@tonic-gate 	return (Vector)configuredScopes.clone();
8520Sstevel@tonic-gate     }
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate     // Return SA scopes.
8550Sstevel@tonic-gate 
getSAOnlyScopes()8560Sstevel@tonic-gate     Vector getSAOnlyScopes() {
8570Sstevel@tonic-gate 	return (Vector)saOnlyScopes.clone();
8580Sstevel@tonic-gate 
8590Sstevel@tonic-gate     }
8600Sstevel@tonic-gate 
8610Sstevel@tonic-gate     // Return the configured scopes for the SA.
8620Sstevel@tonic-gate 
getSAConfiguredScopes()8630Sstevel@tonic-gate     Vector getSAConfiguredScopes() {
8640Sstevel@tonic-gate 	return (Vector)saConfiguredScopes.clone();
8650Sstevel@tonic-gate 
8660Sstevel@tonic-gate     }
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate     // Add scopes discovered during preconfigured DA contact.
8690Sstevel@tonic-gate     //  These count as configured scopes.
8700Sstevel@tonic-gate 
addPreconfiguredDAScopes(Vector scopes)8710Sstevel@tonic-gate     void addPreconfiguredDAScopes(Vector scopes) {
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate 	int i, n = scopes.size();
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
8760Sstevel@tonic-gate 	    Object scope = scopes.elementAt(i);
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 	    if (!configuredScopes.contains(scope)) {
8790Sstevel@tonic-gate 		configuredScopes.addElement(scope);
8800Sstevel@tonic-gate 
8810Sstevel@tonic-gate 	    }
8820Sstevel@tonic-gate 
8830Sstevel@tonic-gate 	    // There better be none extra here for the SA server/DA.
8840Sstevel@tonic-gate 
8850Sstevel@tonic-gate 	    if (isSA() || isDA()) {
8860Sstevel@tonic-gate 		Assert.slpassert(saConfiguredScopes.contains(scope),
8870Sstevel@tonic-gate 			      "sa_new_scope",
8880Sstevel@tonic-gate 			      new Object[] {scope, saConfiguredScopes});
8890Sstevel@tonic-gate 
8900Sstevel@tonic-gate 	    }
8910Sstevel@tonic-gate 	}
8920Sstevel@tonic-gate     }
8930Sstevel@tonic-gate 
8940Sstevel@tonic-gate     // Initialize the scopes list on property.
8950Sstevel@tonic-gate 
initializeScopes(String prop)8960Sstevel@tonic-gate     private Vector initializeScopes(String prop) {
8970Sstevel@tonic-gate 
8980Sstevel@tonic-gate 	String sScopes = System.getProperty(prop);
8990Sstevel@tonic-gate 
9000Sstevel@tonic-gate 	if (sScopes == null || sScopes.length() <= 0) {
9010Sstevel@tonic-gate 	    return new Vector();
9020Sstevel@tonic-gate 	}
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate 	try {
9050Sstevel@tonic-gate 
9060Sstevel@tonic-gate 	    Vector vv =
9070Sstevel@tonic-gate 		SrvLocHeader.parseCommaSeparatedListIn(sScopes, true);
9080Sstevel@tonic-gate 
9090Sstevel@tonic-gate 	    // Unescape scope strings.
9100Sstevel@tonic-gate 
9110Sstevel@tonic-gate 	    SLPHeaderV2.unescapeScopeStrings(vv);
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 	    // Validate, lower case scope names.
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate 	    DATable.validateScopes(vv, getLocale());
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate 	    if (vv.size() > 0) {
9180Sstevel@tonic-gate 		return vv;
9190Sstevel@tonic-gate 	    }
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
9220Sstevel@tonic-gate 	    writeLog("syntax_error_prop",
9230Sstevel@tonic-gate 		     new Object[] {
9240Sstevel@tonic-gate 		prop,
9250Sstevel@tonic-gate 		    sScopes});
9260Sstevel@tonic-gate 
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 	}
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 	return new Vector();
9310Sstevel@tonic-gate     }
9320Sstevel@tonic-gate 
9330Sstevel@tonic-gate     // Vector of preconfigured DAs. Read only after initialized.
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate     private Vector preconfiguredDAs = null;
9360Sstevel@tonic-gate 
9370Sstevel@tonic-gate     // Return a vector of DA addresses.
9380Sstevel@tonic-gate 
getPreconfiguredDAs()9390Sstevel@tonic-gate     Vector getPreconfiguredDAs() {
9400Sstevel@tonic-gate 	return (Vector)preconfiguredDAs.clone();
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate     }
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate     // Initialize preconfigured DA list.
9450Sstevel@tonic-gate 
initializePreconfiguredDAs()9460Sstevel@tonic-gate     private Vector initializePreconfiguredDAs() {
9470Sstevel@tonic-gate 	String sDAList = System.getProperty("net.slp.DAAddresses", "");
9480Sstevel@tonic-gate 	Vector ret = new Vector();
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 	sDAList.trim();
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate 	if (sDAList.length() <= 0) {
9530Sstevel@tonic-gate 	    return ret;
9540Sstevel@tonic-gate 
9550Sstevel@tonic-gate 	}
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 	try {
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate 	    ret = SrvLocHeader.parseCommaSeparatedListIn(sDAList, true);
9600Sstevel@tonic-gate 
9610Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
9620Sstevel@tonic-gate 
9630Sstevel@tonic-gate 	    writeLog("syntax_error_prop",
9640Sstevel@tonic-gate 		     new Object[] {"net.slp.DAAddress", sDAList});
9650Sstevel@tonic-gate 
9660Sstevel@tonic-gate 	    return ret;
9670Sstevel@tonic-gate 
9680Sstevel@tonic-gate 	}
9690Sstevel@tonic-gate 
9700Sstevel@tonic-gate 	// Convert to InetAddress objects.
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate 	int i;
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate 	for (i = 0; i < ret.size(); i++) {
9750Sstevel@tonic-gate 	    String da = "";
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate 	    try {
9780Sstevel@tonic-gate 		da = ((String)ret.elementAt(i)).trim();
9790Sstevel@tonic-gate 		InetAddress daAddr = InetAddress.getByName(da);
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate 		ret.setElementAt(daAddr, i);
9820Sstevel@tonic-gate 
9830Sstevel@tonic-gate 	    } catch (UnknownHostException ex) {
9840Sstevel@tonic-gate 
9850Sstevel@tonic-gate 		writeLog("resolve_failed",
9860Sstevel@tonic-gate 			 new Object[] {da});
9870Sstevel@tonic-gate 
9880Sstevel@tonic-gate 		/*
9890Sstevel@tonic-gate 		 *  Must decrement the index 'i' otherwise the next iteration
9900Sstevel@tonic-gate 		 *  around the loop will miss the element immediately after
9910Sstevel@tonic-gate 		 *  the element removed.
9920Sstevel@tonic-gate 		 *
9930Sstevel@tonic-gate 		 *  WARNING: Do not use 'i' again until the loop has
9940Sstevel@tonic-gate 		 *           iterated as it may, after decrementing,
9950Sstevel@tonic-gate 		 *           be negative.
9960Sstevel@tonic-gate 		 */
9970Sstevel@tonic-gate 		ret.removeElementAt(i);
9980Sstevel@tonic-gate 		i--;
9990Sstevel@tonic-gate 		continue;
10000Sstevel@tonic-gate 	    }
10010Sstevel@tonic-gate 	}
10020Sstevel@tonic-gate 
10030Sstevel@tonic-gate 
10040Sstevel@tonic-gate 	return ret;
10050Sstevel@tonic-gate     }
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate     // ------------------------------------------------------------
10080Sstevel@tonic-gate     // SLPv1 Support Switches
10090Sstevel@tonic-gate     //
10100Sstevel@tonic-gate 
getSLPv1NotSupported()10110Sstevel@tonic-gate     boolean getSLPv1NotSupported() {// not official!
10120Sstevel@tonic-gate 	return Boolean.getBoolean("sun.net.slp.SLPv1NotSupported");
10130Sstevel@tonic-gate 
10140Sstevel@tonic-gate     }
10150Sstevel@tonic-gate 
getAcceptSLPv1UnscopedRegs()10160Sstevel@tonic-gate     boolean getAcceptSLPv1UnscopedRegs() {// not official!
10170Sstevel@tonic-gate 
10180Sstevel@tonic-gate 	if (!getSLPv1NotSupported()) {
10190Sstevel@tonic-gate 	    return Boolean.getBoolean("sun.net.slp.acceptSLPv1UnscopedRegs");
10200Sstevel@tonic-gate 
10210Sstevel@tonic-gate 	}
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate 	return false;
10240Sstevel@tonic-gate     }
10250Sstevel@tonic-gate 
10260Sstevel@tonic-gate     // ------------------------------------------------------------
10270Sstevel@tonic-gate     // Accessor for SLPConfig object
10280Sstevel@tonic-gate     //
10290Sstevel@tonic-gate 
10300Sstevel@tonic-gate     protected static SLPConfig theSLPConfig = null;
10310Sstevel@tonic-gate 
getSLPConfig()10320Sstevel@tonic-gate     static SLPConfig getSLPConfig() {
10330Sstevel@tonic-gate 
10340Sstevel@tonic-gate 	if (theSLPConfig == null) {
10350Sstevel@tonic-gate 	    theSLPConfig = new SLPConfig();
10360Sstevel@tonic-gate 	}
10370Sstevel@tonic-gate 
10380Sstevel@tonic-gate 	return theSLPConfig;
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate     }
10410Sstevel@tonic-gate 
10420Sstevel@tonic-gate     /**
10430Sstevel@tonic-gate      * @return Maximum number of messages/objects to return.
10440Sstevel@tonic-gate      */
10450Sstevel@tonic-gate 
getMaximumResults()10460Sstevel@tonic-gate     int getMaximumResults()  {
10470Sstevel@tonic-gate 	int i = Integer.getInteger("net.slp.maxResults",
10480Sstevel@tonic-gate 				   Defaults.iMaximumResults).intValue();
10490Sstevel@tonic-gate 	if (i == -1) {
10500Sstevel@tonic-gate 	    i = Integer.MAX_VALUE;
10510Sstevel@tonic-gate 
10520Sstevel@tonic-gate 	}
10530Sstevel@tonic-gate 
10540Sstevel@tonic-gate 	if (OKBound(i, 1, Integer.MAX_VALUE)) {
10550Sstevel@tonic-gate 	    return i;
10560Sstevel@tonic-gate 
10570Sstevel@tonic-gate 	} else {
10580Sstevel@tonic-gate 
10590Sstevel@tonic-gate 	    writeLog("bad_prop_tag",
10600Sstevel@tonic-gate 		     new Object[] {
10610Sstevel@tonic-gate 		"net.slp.maxResults"});
10620Sstevel@tonic-gate 
10630Sstevel@tonic-gate 	    return Defaults.iMaximumResults;
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate 	}
10660Sstevel@tonic-gate     }
10670Sstevel@tonic-gate 
10680Sstevel@tonic-gate     /**
10690Sstevel@tonic-gate      * Convert a language tag into a locale.
10700Sstevel@tonic-gate      */
10710Sstevel@tonic-gate 
langTagToLocale(String ltag)10720Sstevel@tonic-gate     static Locale langTagToLocale(String ltag) {
10730Sstevel@tonic-gate 
10740Sstevel@tonic-gate 	// We treat the first part as the ISO 639 language and the
10750Sstevel@tonic-gate 	// second part as the ISO 3166 country tag, even though RFC
10760Sstevel@tonic-gate 	// 1766 doesn't necessarily require that. We should probably
10770Sstevel@tonic-gate 	// use a lookup table here to determine if they are correct.
10780Sstevel@tonic-gate 
10790Sstevel@tonic-gate 	StringTokenizer tk = new StringTokenizer(ltag, "-");
10800Sstevel@tonic-gate 	String lang = "";
10810Sstevel@tonic-gate 	String country = "";
10820Sstevel@tonic-gate 
10830Sstevel@tonic-gate 	if (tk.hasMoreTokens()) {
10840Sstevel@tonic-gate 	    lang = tk.nextToken();
10850Sstevel@tonic-gate 
10860Sstevel@tonic-gate 	    if (tk.hasMoreTokens()) {
10870Sstevel@tonic-gate 		country = tk.nextToken("");
10880Sstevel@tonic-gate 					// country name may have "-" in it...
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate 	    }
10910Sstevel@tonic-gate 	}
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 	return new Locale(lang, country);
10940Sstevel@tonic-gate     }
10950Sstevel@tonic-gate 
10960Sstevel@tonic-gate     /**
10970Sstevel@tonic-gate      * Convert a Locale object into a language tag for output.
10980Sstevel@tonic-gate      *
10990Sstevel@tonic-gate      * @param locale The Locale.
11000Sstevel@tonic-gate      * @return String with the language tag encoded.
11010Sstevel@tonic-gate      */
11020Sstevel@tonic-gate 
localeToLangTag(Locale locale)11030Sstevel@tonic-gate     static String localeToLangTag(Locale locale) {
11040Sstevel@tonic-gate 
11050Sstevel@tonic-gate 	// Construct the language tag.
11060Sstevel@tonic-gate 
11070Sstevel@tonic-gate 	String ltag = locale.getCountry();
11080Sstevel@tonic-gate 	ltag = locale.getLanguage() + (ltag.length() <= 0 ? "" : ("-" + ltag));
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate 	return ltag;
11110Sstevel@tonic-gate 
11120Sstevel@tonic-gate     }
11130Sstevel@tonic-gate 
11140Sstevel@tonic-gate     /**
11150Sstevel@tonic-gate      * @return the language requests will be made in.
11160Sstevel@tonic-gate      */
getLocale()11170Sstevel@tonic-gate     static Locale  getLocale()    {
11180Sstevel@tonic-gate 	String s = System.getProperty("net.slp.locale");
11190Sstevel@tonic-gate 
11200Sstevel@tonic-gate 	if (s != null && s.length() > 0) {
11210Sstevel@tonic-gate 	    return langTagToLocale(s);
11220Sstevel@tonic-gate 
11230Sstevel@tonic-gate 	} else {
11240Sstevel@tonic-gate 
11250Sstevel@tonic-gate 	    // Return the Java default if the SLP property is not set.
11260Sstevel@tonic-gate 
11270Sstevel@tonic-gate 	    return Locale.getDefault();
11280Sstevel@tonic-gate 
11290Sstevel@tonic-gate 	}
11300Sstevel@tonic-gate     }
11310Sstevel@tonic-gate 
11320Sstevel@tonic-gate     /**
11330Sstevel@tonic-gate      * @return the InetAddress of the broadcast interface.
11340Sstevel@tonic-gate      */
11350Sstevel@tonic-gate 
11360Sstevel@tonic-gate     static private InetAddress broadcastAddress;
11370Sstevel@tonic-gate 
getBroadcastAddress()11380Sstevel@tonic-gate     static InetAddress getBroadcastAddress() {
11390Sstevel@tonic-gate 	if (broadcastAddress == null) {
11400Sstevel@tonic-gate 
11410Sstevel@tonic-gate 	    try {
11420Sstevel@tonic-gate 		broadcastAddress =
11430Sstevel@tonic-gate 		    InetAddress.getByName(Defaults.sBroadcast);
11440Sstevel@tonic-gate 	    } catch (UnknownHostException uhe) {
11450Sstevel@tonic-gate 
11460Sstevel@tonic-gate 		Assert.slpassert(false,
11470Sstevel@tonic-gate 			      "cast_address_failure",
11480Sstevel@tonic-gate 			      new Object[] {Defaults.sBroadcast});
11490Sstevel@tonic-gate 
11500Sstevel@tonic-gate 	    }
11510Sstevel@tonic-gate 	}
11520Sstevel@tonic-gate 	return broadcastAddress;
11530Sstevel@tonic-gate     }
11540Sstevel@tonic-gate 
11550Sstevel@tonic-gate 
11560Sstevel@tonic-gate     /**
11570Sstevel@tonic-gate      * @return the InetAddress of the multicast group.
11580Sstevel@tonic-gate      */
11590Sstevel@tonic-gate 
11600Sstevel@tonic-gate     static private InetAddress multicastAddress;
11610Sstevel@tonic-gate 
getMulticastAddress()11620Sstevel@tonic-gate     static InetAddress getMulticastAddress() {
11630Sstevel@tonic-gate 	if (multicastAddress == null) {
11640Sstevel@tonic-gate 
11650Sstevel@tonic-gate 	    try {
11660Sstevel@tonic-gate 		multicastAddress =
11670Sstevel@tonic-gate 		    InetAddress.getByName(Defaults.sGeneralSLPMCAddress);
11680Sstevel@tonic-gate 	    } catch (UnknownHostException uhe) {
11690Sstevel@tonic-gate 		Assert.slpassert(false,
11700Sstevel@tonic-gate 			      "cast_address_failure",
11710Sstevel@tonic-gate 			      new Object[] {Defaults.sGeneralSLPMCAddress});
11720Sstevel@tonic-gate 
11730Sstevel@tonic-gate 	    }
11740Sstevel@tonic-gate 	}
11750Sstevel@tonic-gate 	return multicastAddress;
11760Sstevel@tonic-gate     }
11770Sstevel@tonic-gate 
11780Sstevel@tonic-gate     /**
11790Sstevel@tonic-gate      * @return the interfaces on which SLP should listen and transmit.
11800Sstevel@tonic-gate      */
11810Sstevel@tonic-gate 
11820Sstevel@tonic-gate     private static Vector interfaces = null;
11830Sstevel@tonic-gate 
getInterfaces()11840Sstevel@tonic-gate     Vector getInterfaces() {
11850Sstevel@tonic-gate 
11860Sstevel@tonic-gate 	if (interfaces == null) {
11870Sstevel@tonic-gate 	    InetAddress iaLocal = null;
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate 	    // Get local host.
11900Sstevel@tonic-gate 
11910Sstevel@tonic-gate 	    try {
11920Sstevel@tonic-gate 		iaLocal =  InetAddress.getLocalHost();
11930Sstevel@tonic-gate 
11940Sstevel@tonic-gate 	    }  catch (UnknownHostException ex) {
11950Sstevel@tonic-gate 		Assert.slpassert(false,
11960Sstevel@tonic-gate 			      "resolve_failed",
11970Sstevel@tonic-gate 			      new Object[] {"localhost"});
11980Sstevel@tonic-gate 	    }
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate 	    String mcastI = System.getProperty("net.slp.interfaces");
12010Sstevel@tonic-gate 	    interfaces = new Vector();
12020Sstevel@tonic-gate 
12030Sstevel@tonic-gate 	    // Only add local host if nothing else is given.
12040Sstevel@tonic-gate 
12050Sstevel@tonic-gate 	    if (mcastI == null || mcastI.length() <= 0) {
12060Sstevel@tonic-gate 		interfaces.addElement(iaLocal);
12070Sstevel@tonic-gate 		return interfaces;
12080Sstevel@tonic-gate 
12090Sstevel@tonic-gate 	    }
12100Sstevel@tonic-gate 
12110Sstevel@tonic-gate 	    Vector nintr;
12120Sstevel@tonic-gate 
12130Sstevel@tonic-gate 	    try {
12140Sstevel@tonic-gate 
12150Sstevel@tonic-gate 		nintr = SrvLocHeader.parseCommaSeparatedListIn(mcastI, true);
12160Sstevel@tonic-gate 
12170Sstevel@tonic-gate 	    } catch (ServiceLocationException ex) {
12180Sstevel@tonic-gate 		writeLog("syntax_error_prop",
12190Sstevel@tonic-gate 			 new Object[] {
12200Sstevel@tonic-gate 		    "net.slp.multicastInterfaces",
12210Sstevel@tonic-gate 			mcastI});
12220Sstevel@tonic-gate 
12230Sstevel@tonic-gate 		// Add local host.
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate 		interfaces.addElement(iaLocal);
12260Sstevel@tonic-gate 
12270Sstevel@tonic-gate 		return interfaces;
12280Sstevel@tonic-gate 
12290Sstevel@tonic-gate 	    }
12300Sstevel@tonic-gate 
12310Sstevel@tonic-gate 	    // See if they are really there.
12320Sstevel@tonic-gate 
12330Sstevel@tonic-gate 	    int i, n = nintr.size();
12340Sstevel@tonic-gate 
12350Sstevel@tonic-gate 	    for (i = 0; i < n; i++) {
12360Sstevel@tonic-gate 		InetAddress ia;
12370Sstevel@tonic-gate 		String host = (String)nintr.elementAt(i);
12380Sstevel@tonic-gate 
12390Sstevel@tonic-gate 		try {
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate 		    ia = InetAddress.getByName(host);
12420Sstevel@tonic-gate 
12430Sstevel@tonic-gate 		} catch (UnknownHostException ex) {
12440Sstevel@tonic-gate 		    writeLog("unknown_interface",
12450Sstevel@tonic-gate 			     new Object[] {host,
12460Sstevel@tonic-gate 					       "net.slp.multicastInterfaces"});
12470Sstevel@tonic-gate 		    continue;
12480Sstevel@tonic-gate 
12490Sstevel@tonic-gate 		}
12500Sstevel@tonic-gate 
12510Sstevel@tonic-gate 		if (!interfaces.contains(ia)) {
12520Sstevel@tonic-gate 
12530Sstevel@tonic-gate 		    // Add default at beginning.
12540Sstevel@tonic-gate 
12550Sstevel@tonic-gate 		    if (ia.equals(iaLocal)) {
12560Sstevel@tonic-gate 			interfaces.insertElementAt(ia, 0);
12570Sstevel@tonic-gate 
12580Sstevel@tonic-gate 		    } else {
12590Sstevel@tonic-gate 			interfaces.addElement(ia);
12600Sstevel@tonic-gate 
12610Sstevel@tonic-gate 		    }
12620Sstevel@tonic-gate 		}
12630Sstevel@tonic-gate 	    }
12640Sstevel@tonic-gate 	}
12650Sstevel@tonic-gate 
12660Sstevel@tonic-gate 	return interfaces;
12670Sstevel@tonic-gate 
12680Sstevel@tonic-gate     }
12690Sstevel@tonic-gate 
12700Sstevel@tonic-gate     /**
12710Sstevel@tonic-gate      * @return An InetAddress object representing 127.0.0.1
12720Sstevel@tonic-gate      */
getLoopback()12730Sstevel@tonic-gate     InetAddress getLoopback() {
12740Sstevel@tonic-gate 	InetAddress iaLoopback = null;
12750Sstevel@tonic-gate 
12760Sstevel@tonic-gate 	try {
12770Sstevel@tonic-gate 	    iaLoopback = InetAddress.getByName(Defaults.LOOPBACK_ADDRESS);
12780Sstevel@tonic-gate 
12790Sstevel@tonic-gate 	}  catch (UnknownHostException ex) {
12800Sstevel@tonic-gate 	    Assert.slpassert(false,
12810Sstevel@tonic-gate 			  "resolve_failed",
12820Sstevel@tonic-gate 			  new Object[] {"localhost loopback"});
12830Sstevel@tonic-gate 	}
12840Sstevel@tonic-gate 
12850Sstevel@tonic-gate 	return iaLoopback;
12860Sstevel@tonic-gate     }
12870Sstevel@tonic-gate 
12880Sstevel@tonic-gate     /**
12890Sstevel@tonic-gate      * @return The default interface, which should be the first in the
12900Sstevel@tonic-gate      *         interfaces vector Vector.
12910Sstevel@tonic-gate      */
12920Sstevel@tonic-gate 
getLocalHost()12930Sstevel@tonic-gate     InetAddress getLocalHost() {
12940Sstevel@tonic-gate 	Vector inter = getInterfaces();
12950Sstevel@tonic-gate 	return (InetAddress)inter.elementAt(0);
12960Sstevel@tonic-gate 
12970Sstevel@tonic-gate     }
12980Sstevel@tonic-gate 
12990Sstevel@tonic-gate     // Return true if the address is one of the local interfaces.
13000Sstevel@tonic-gate 
isLocalHostSource(InetAddress addr)13010Sstevel@tonic-gate     boolean isLocalHostSource(InetAddress addr) {
13020Sstevel@tonic-gate 
13030Sstevel@tonic-gate 	// First check loopback
13040Sstevel@tonic-gate 
13050Sstevel@tonic-gate 	if (addr.equals(getLoopback())) {
13060Sstevel@tonic-gate 	    return true;
13070Sstevel@tonic-gate 
13080Sstevel@tonic-gate 	}
13090Sstevel@tonic-gate 
13100Sstevel@tonic-gate 	return interfaces.contains(addr);
13110Sstevel@tonic-gate 
13120Sstevel@tonic-gate     }
13130Sstevel@tonic-gate 
13140Sstevel@tonic-gate     // -----------------
13150Sstevel@tonic-gate     // Timeouts
13160Sstevel@tonic-gate     //
13170Sstevel@tonic-gate 
13180Sstevel@tonic-gate     // Return the maximum wait for multicast convergence.
13190Sstevel@tonic-gate 
13200Sstevel@tonic-gate     final static private int iMultiMin = 1000;  // one second
13210Sstevel@tonic-gate     final static private int iMultiMax = 60000; // one minute
13220Sstevel@tonic-gate 
getMulticastMaximumWait()13230Sstevel@tonic-gate     int getMulticastMaximumWait() {
13240Sstevel@tonic-gate 
13250Sstevel@tonic-gate 	return getIntProperty("net.slp.multicastMaximumWait",
13260Sstevel@tonic-gate 			      Defaults.iMulticastMaxWait,
13270Sstevel@tonic-gate 			      iMultiMin,
13280Sstevel@tonic-gate 			      iMultiMax);
13290Sstevel@tonic-gate     }
13300Sstevel@tonic-gate 
13310Sstevel@tonic-gate     /*
13320Sstevel@tonic-gate      * @return Vector of timeouts for multicast convergence.
13330Sstevel@tonic-gate      */
13340Sstevel@tonic-gate 
getMulticastTimeouts()13350Sstevel@tonic-gate     int[] getMulticastTimeouts() {
13360Sstevel@tonic-gate 	int[] timeouts = parseTimeouts("net.slp.multicastTimeouts",
13370Sstevel@tonic-gate 			     Defaults.a_iConvergeTimeout);
13380Sstevel@tonic-gate 
13390Sstevel@tonic-gate 	timeouts = capTimeouts("net.slp.multicastTimeouts",
13400Sstevel@tonic-gate 			       timeouts,
13410Sstevel@tonic-gate 			       false,
13420Sstevel@tonic-gate 			       0,
13430Sstevel@tonic-gate 			       0);
13440Sstevel@tonic-gate 
13450Sstevel@tonic-gate 	return timeouts;
13460Sstevel@tonic-gate     }
13470Sstevel@tonic-gate 
13480Sstevel@tonic-gate     /**
13490Sstevel@tonic-gate      * @return Vector of timeouts to try for datagram transmission.
13500Sstevel@tonic-gate      */
13510Sstevel@tonic-gate 
getDatagramTimeouts()13520Sstevel@tonic-gate     int[] getDatagramTimeouts() {
13530Sstevel@tonic-gate 	int[] timeouts = parseTimeouts("net.slp.datagramTimeouts",
13540Sstevel@tonic-gate 			     Defaults.a_iDatagramTimeout);
13550Sstevel@tonic-gate 
13560Sstevel@tonic-gate 	timeouts = capTimeouts("net.slp.datagramTimeouts",
13570Sstevel@tonic-gate 			       timeouts,
13580Sstevel@tonic-gate 			       true,
13590Sstevel@tonic-gate 			       iMultiMin,
13600Sstevel@tonic-gate 			       iMultiMax);
13610Sstevel@tonic-gate 
13620Sstevel@tonic-gate 	return timeouts;
13630Sstevel@tonic-gate     }
13640Sstevel@tonic-gate 
13650Sstevel@tonic-gate     /**
13660Sstevel@tonic-gate      * @return Vector of timeouts for DA discovery multicast.
13670Sstevel@tonic-gate      */
13680Sstevel@tonic-gate 
getDADiscoveryTimeouts()13690Sstevel@tonic-gate     int[] getDADiscoveryTimeouts() {
13700Sstevel@tonic-gate 	int[] timeouts = parseTimeouts("net.slp.DADiscoveryTimeouts",
13710Sstevel@tonic-gate 			     Defaults.a_iDADiscoveryTimeout);
13720Sstevel@tonic-gate 
13730Sstevel@tonic-gate 	timeouts = capTimeouts("net.slp.DADiscoveryTimeouts",
13740Sstevel@tonic-gate 				timeouts,
13750Sstevel@tonic-gate 				false,
13760Sstevel@tonic-gate 				0,
13770Sstevel@tonic-gate 				0);
13780Sstevel@tonic-gate 
13790Sstevel@tonic-gate 	return timeouts;
13800Sstevel@tonic-gate     }
13810Sstevel@tonic-gate 
13820Sstevel@tonic-gate     /**
13830Sstevel@tonic-gate      *  This method ensures that all the timeouts are within valid ranges.
13840Sstevel@tonic-gate      *  The sum of all timeouts for the given property name must not
13850Sstevel@tonic-gate      *  exceed the value returned by <i>getMulticastMaximumWait()</i>. If
13860Sstevel@tonic-gate      *  the sum of all timeouts does exceed the maximum wait period the
13870Sstevel@tonic-gate      *  timeouts are averaged out so that the sum equals the maximum wait
13880Sstevel@tonic-gate      *  period.
13890Sstevel@tonic-gate      *	<br>
13900Sstevel@tonic-gate      *  Additional range checking is also performed when <i>rangeCheck</i>
13910Sstevel@tonic-gate      *  is true. Then the sum of all timeouts must also be between <i>min</i>
13920Sstevel@tonic-gate      *  and <i>max</i>. If the sum of all timeouts is not within the range
13930Sstevel@tonic-gate      *  the average is taken from the closest range boundary.
13940Sstevel@tonic-gate      *
13950Sstevel@tonic-gate      *  @param property
13960Sstevel@tonic-gate      *	    Name of timeout property being capped. This is only present for
13970Sstevel@tonic-gate      *	    reporting purposes and no actual manipulation of the property
13980Sstevel@tonic-gate      *      is made within this method.
13990Sstevel@tonic-gate      *  @param timeouts
14000Sstevel@tonic-gate      *      Array of timeout values.
14010Sstevel@tonic-gate      *  @param rangeCheck
14020Sstevel@tonic-gate      *      Indicator of whether additional range checking is required. When
14030Sstevel@tonic-gate      *      false <i>min</i> and <i>max</i> are ignored.
14040Sstevel@tonic-gate      *  @param min
14050Sstevel@tonic-gate      *      Additional range checking lower boundary.
14060Sstevel@tonic-gate      *  @param max
14070Sstevel@tonic-gate      *      Additional range checking upper boundary.
14080Sstevel@tonic-gate      *  @return
14090Sstevel@tonic-gate      *      Array of capped timeouts. Note this may be the same array as
14100Sstevel@tonic-gate      *      passed in (<i>timeouts</i>).
14110Sstevel@tonic-gate      */
capTimeouts(String property, int[] timeouts, boolean rangeCheck, int min, int max)14120Sstevel@tonic-gate     private int[] capTimeouts(String property,
14130Sstevel@tonic-gate 			      int[] timeouts,
14140Sstevel@tonic-gate 			      boolean rangeCheck,
14150Sstevel@tonic-gate 			      int min,
14160Sstevel@tonic-gate 			      int max) {
14170Sstevel@tonic-gate 
14180Sstevel@tonic-gate 	int averagedTimeout;
14190Sstevel@tonic-gate 	int totalWait = 0;
14200Sstevel@tonic-gate 
14210Sstevel@tonic-gate 	for (int index = 0; index < timeouts.length; index++) {
14220Sstevel@tonic-gate 	    totalWait += timeouts[index];
14230Sstevel@tonic-gate 	}
14240Sstevel@tonic-gate 
14250Sstevel@tonic-gate 	if (rangeCheck) {
14260Sstevel@tonic-gate 	    // If sum of timeouts within limits then finished.
14270Sstevel@tonic-gate 	    if (totalWait >= min && totalWait <= max) {
14280Sstevel@tonic-gate 		return timeouts;
14290Sstevel@tonic-gate 	    }
14300Sstevel@tonic-gate 
14310Sstevel@tonic-gate 	    // Average out the timeouts so the sum is equal to the closest
14320Sstevel@tonic-gate 	    // range boundary.
14330Sstevel@tonic-gate 	    if (totalWait < min) {
14340Sstevel@tonic-gate 		averagedTimeout = min / timeouts.length;
14350Sstevel@tonic-gate 	    } else {
14360Sstevel@tonic-gate 		averagedTimeout = max / timeouts.length;
14370Sstevel@tonic-gate 	    }
14380Sstevel@tonic-gate 
14390Sstevel@tonic-gate 	    writeLog("capped_range_timeout_prop",
14400Sstevel@tonic-gate 		     new Object[] {property,
14410Sstevel@tonic-gate 				   String.valueOf(totalWait),
14420Sstevel@tonic-gate 				   String.valueOf(min),
14430Sstevel@tonic-gate 				   String.valueOf(max),
14440Sstevel@tonic-gate 				   String.valueOf(timeouts.length),
14450Sstevel@tonic-gate 				   String.valueOf(averagedTimeout)});
14460Sstevel@tonic-gate 	} else {
14470Sstevel@tonic-gate 	    // Sum of all timeouts must not exceed this value.
14480Sstevel@tonic-gate 	    int maximumWait = getMulticastMaximumWait();
14490Sstevel@tonic-gate 
14500Sstevel@tonic-gate 	    // If sum of timeouts within limits then finished.
14510Sstevel@tonic-gate 	    if (totalWait <= maximumWait) {
14520Sstevel@tonic-gate 		return timeouts;
14530Sstevel@tonic-gate 	    }
14540Sstevel@tonic-gate 
14550Sstevel@tonic-gate 	    // Average out the timeouts so the sum is equal to the maximum
14560Sstevel@tonic-gate 	    // timeout.
14570Sstevel@tonic-gate 	    averagedTimeout = maximumWait / timeouts.length;
14580Sstevel@tonic-gate 
14590Sstevel@tonic-gate 	    writeLog("capped_timeout_prop",
14600Sstevel@tonic-gate 		     new Object[] {property,
14610Sstevel@tonic-gate 				   String.valueOf(totalWait),
14620Sstevel@tonic-gate 				   String.valueOf(maximumWait),
14630Sstevel@tonic-gate 				   String.valueOf(timeouts.length),
14640Sstevel@tonic-gate 				   String.valueOf(averagedTimeout)});
14650Sstevel@tonic-gate 	}
14660Sstevel@tonic-gate 
14670Sstevel@tonic-gate 	for (int index = 0; index < timeouts.length; index++) {
14680Sstevel@tonic-gate 	    timeouts[index] = averagedTimeout;
14690Sstevel@tonic-gate 	}
14700Sstevel@tonic-gate 
14710Sstevel@tonic-gate 	return timeouts;
14720Sstevel@tonic-gate     }
14730Sstevel@tonic-gate 
parseTimeouts(String property, int[] defaults)14740Sstevel@tonic-gate     private int[] parseTimeouts(String property, int[] defaults) {
14750Sstevel@tonic-gate 
14760Sstevel@tonic-gate 	String sTimeouts = System.getProperty(property);
14770Sstevel@tonic-gate 
14780Sstevel@tonic-gate 	if (sTimeouts == null || sTimeouts.length() <= 0) {
14790Sstevel@tonic-gate 	    return defaults;
14800Sstevel@tonic-gate 
14810Sstevel@tonic-gate 	}
14820Sstevel@tonic-gate 
14830Sstevel@tonic-gate 	Vector timeouts = null;
14840Sstevel@tonic-gate 
14850Sstevel@tonic-gate 	try {
14860Sstevel@tonic-gate 	    timeouts = SrvLocHeader.parseCommaSeparatedListIn(sTimeouts, true);
14870Sstevel@tonic-gate 
14880Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
14890Sstevel@tonic-gate 	    writeLog("syntax_error_prop",
14900Sstevel@tonic-gate 		     new Object[] {property, sTimeouts});
14910Sstevel@tonic-gate 	    return defaults;
14920Sstevel@tonic-gate 
14930Sstevel@tonic-gate 	}
14940Sstevel@tonic-gate 
14950Sstevel@tonic-gate 	int iCount = 0;
14960Sstevel@tonic-gate 	int[] iTOs = new int[timeouts.size()];
14970Sstevel@tonic-gate 
14980Sstevel@tonic-gate 	for (Enumeration en = timeouts.elements(); en.hasMoreElements(); ) {
14990Sstevel@tonic-gate 	    String s1 = (String)en.nextElement();
15000Sstevel@tonic-gate 
15010Sstevel@tonic-gate 	    try {
15020Sstevel@tonic-gate 		iTOs[iCount] = Integer.parseInt(s1);
15030Sstevel@tonic-gate 
15040Sstevel@tonic-gate 	    }	catch (NumberFormatException nfe) {
15050Sstevel@tonic-gate 		writeLog("syntax_error_prop",
15060Sstevel@tonic-gate 			 new Object[] {property, sTimeouts});
15070Sstevel@tonic-gate 		return defaults;
15080Sstevel@tonic-gate 
15090Sstevel@tonic-gate 	    }
15100Sstevel@tonic-gate 
15110Sstevel@tonic-gate 	    if (iTOs[iCount] < 0) {
15120Sstevel@tonic-gate 		writeLog("invalid_timeout_prop",
15130Sstevel@tonic-gate 			 new Object[] {property, String.valueOf(iTOs[iCount])});
15140Sstevel@tonic-gate 		return defaults;
15150Sstevel@tonic-gate 	    }
15160Sstevel@tonic-gate 
15170Sstevel@tonic-gate 	    iCount++;
15180Sstevel@tonic-gate 	}
15190Sstevel@tonic-gate 
15200Sstevel@tonic-gate 	return iTOs;
15210Sstevel@tonic-gate     }
15220Sstevel@tonic-gate 
15230Sstevel@tonic-gate     // -----------------------------
15240Sstevel@tonic-gate     // SLP Time Calculation
15250Sstevel@tonic-gate     //
15260Sstevel@tonic-gate 
15270Sstevel@tonic-gate     /**
15280Sstevel@tonic-gate      * Returns the number of seconds since 00:00 Universal Coordinated
15290Sstevel@tonic-gate      * Time, January 1, 1970.
15300Sstevel@tonic-gate      *
15310Sstevel@tonic-gate      * Java returns the number of milliseconds, so all the method does is
15320Sstevel@tonic-gate      * divide by 1000.
15330Sstevel@tonic-gate      *
15340Sstevel@tonic-gate      * This implementation still will have a problem when the Java time
15350Sstevel@tonic-gate      * values wraps, but there isn't much we can do now.
15360Sstevel@tonic-gate      */
currentSLPTime()15370Sstevel@tonic-gate     static long currentSLPTime() {
15380Sstevel@tonic-gate 	return (System.currentTimeMillis() / 1000);
15390Sstevel@tonic-gate     }
15400Sstevel@tonic-gate 
15410Sstevel@tonic-gate     /* security */
15420Sstevel@tonic-gate 
15430Sstevel@tonic-gate     // Indicates whether security class is available.
15440Sstevel@tonic-gate 
getSecurityEnabled()15450Sstevel@tonic-gate     boolean getSecurityEnabled() {
15460Sstevel@tonic-gate 	return securityEnabled;
15470Sstevel@tonic-gate 
15480Sstevel@tonic-gate     }
15490Sstevel@tonic-gate 
15500Sstevel@tonic-gate     private static boolean securityEnabled;
15510Sstevel@tonic-gate 
15520Sstevel@tonic-gate     // Indicates whether the securityEnabled property is true
15530Sstevel@tonic-gate 
getHasSecurity()15540Sstevel@tonic-gate     boolean getHasSecurity() {
15550Sstevel@tonic-gate 	return securityEnabled &&
15560Sstevel@tonic-gate 	    (new Boolean(System.getProperty("net.slp.securityEnabled",
15570Sstevel@tonic-gate 					    "false")).booleanValue());
15580Sstevel@tonic-gate     }
15590Sstevel@tonic-gate 
15600Sstevel@tonic-gate     // I18N Support.
15610Sstevel@tonic-gate 
15620Sstevel@tonic-gate     private static final String BASE_BUNDLE_NAME = "com/sun/slp/ClientLib";
15630Sstevel@tonic-gate 
getMessageBundle(Locale locale)15640Sstevel@tonic-gate     ResourceBundle getMessageBundle(Locale locale) {
15650Sstevel@tonic-gate 
15660Sstevel@tonic-gate 	ResourceBundle msgBundle = null;
15670Sstevel@tonic-gate 
15680Sstevel@tonic-gate 	// First try the Solaris Java locale area
15690Sstevel@tonic-gate 
15700Sstevel@tonic-gate 	try {
15710Sstevel@tonic-gate 	    URL[] urls = new URL[] {new URL("file:/usr/share/lib/locale/")};
15720Sstevel@tonic-gate 
15730Sstevel@tonic-gate 	    URLClassLoader ld = new URLClassLoader(urls);
15740Sstevel@tonic-gate 
15750Sstevel@tonic-gate 	    msgBundle = ResourceBundle.getBundle(BASE_BUNDLE_NAME, locale, ld);
15760Sstevel@tonic-gate 
15770Sstevel@tonic-gate 	    return msgBundle;
15780Sstevel@tonic-gate 	} catch (MalformedURLException e) {	// shouldn't get here
15790Sstevel@tonic-gate 	} catch (MissingResourceException ex) {
15800Sstevel@tonic-gate 	    System.err.println("Missing resource bundle ``"+
15810Sstevel@tonic-gate 			       "/usr/share/lib/locale/" + BASE_BUNDLE_NAME +
15820Sstevel@tonic-gate 			       "'' for locale ``" +
15830Sstevel@tonic-gate 			       locale + "''; trying default...");
15840Sstevel@tonic-gate 	}
15850Sstevel@tonic-gate 
15860Sstevel@tonic-gate 	try {
15870Sstevel@tonic-gate 	    msgBundle = ResourceBundle.getBundle(BASE_BUNDLE_NAME, locale);
15880Sstevel@tonic-gate 
15890Sstevel@tonic-gate 	} catch (MissingResourceException ex) {  // can't localize this one!
15900Sstevel@tonic-gate 
15910Sstevel@tonic-gate 	    // We can't print out to the log, because we may be in the
15920Sstevel@tonic-gate 	    //  process of trying to.
15930Sstevel@tonic-gate 
15940Sstevel@tonic-gate 	    System.err.println("Missing resource bundle ``"+
15950Sstevel@tonic-gate 			       BASE_BUNDLE_NAME+
15960Sstevel@tonic-gate 			       "'' for locale ``"+
15970Sstevel@tonic-gate 			       locale+
15980Sstevel@tonic-gate 			       "''");
15990Sstevel@tonic-gate 	    // Hosed if the default locale is missing.
16000Sstevel@tonic-gate 
16010Sstevel@tonic-gate 	    if (locale.equals(Defaults.locale)) {
16020Sstevel@tonic-gate 
16030Sstevel@tonic-gate 		System.err.println("Exiting...");
16040Sstevel@tonic-gate 		System.exit(1);
16050Sstevel@tonic-gate 	    }
16060Sstevel@tonic-gate 
16070Sstevel@tonic-gate 	    // Otherwise, return the default locale.
16080Sstevel@tonic-gate 
16090Sstevel@tonic-gate 	    System.err.println("Using SLP default locale ``" +
16100Sstevel@tonic-gate 			       Defaults.locale +
16110Sstevel@tonic-gate 			       "''");
16120Sstevel@tonic-gate 
16130Sstevel@tonic-gate 	    msgBundle = getMessageBundle(Defaults.locale);
16140Sstevel@tonic-gate 
16150Sstevel@tonic-gate 	}
16160Sstevel@tonic-gate 
16170Sstevel@tonic-gate 	return msgBundle;
16180Sstevel@tonic-gate     }
16190Sstevel@tonic-gate 
formatMessage(String msgTag, Object[] params)16200Sstevel@tonic-gate     String formatMessage(String msgTag, Object[] params) {
16210Sstevel@tonic-gate 	ResourceBundle bundle = getMessageBundle(getLocale());
16220Sstevel@tonic-gate 	return formatMessageInternal(msgTag, params, bundle);
16230Sstevel@tonic-gate 
16240Sstevel@tonic-gate     }
16250Sstevel@tonic-gate 
16260Sstevel@tonic-gate     // MessageFormat is picky about types. Convert the params into strings.
16270Sstevel@tonic-gate 
convertToString(Object[] params)16280Sstevel@tonic-gate     static void convertToString(Object[] params) {
16290Sstevel@tonic-gate 	int i, n = params.length;
16300Sstevel@tonic-gate 
16310Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
16320Sstevel@tonic-gate 
16330Sstevel@tonic-gate 	    if (params[i] != null) {
16340Sstevel@tonic-gate 		params[i] = params[i].toString();
16350Sstevel@tonic-gate 
16360Sstevel@tonic-gate 	    } else {
16370Sstevel@tonic-gate 		params[i] = "<null>";
16380Sstevel@tonic-gate 
16390Sstevel@tonic-gate 	    }
16400Sstevel@tonic-gate 	}
16410Sstevel@tonic-gate     }
16420Sstevel@tonic-gate 
16430Sstevel@tonic-gate     static String
formatMessageInternal(String msgTag, Object[] params, ResourceBundle bundle)16440Sstevel@tonic-gate 	formatMessageInternal(String msgTag,
16450Sstevel@tonic-gate 			      Object[] params,
16460Sstevel@tonic-gate 			      ResourceBundle bundle) {
16470Sstevel@tonic-gate 	String pattern = "";
16480Sstevel@tonic-gate 
16490Sstevel@tonic-gate 	try {
16500Sstevel@tonic-gate 	    pattern = bundle.getString(msgTag);
16510Sstevel@tonic-gate 
16520Sstevel@tonic-gate 	} catch (MissingResourceException ex) {
16530Sstevel@tonic-gate 
16540Sstevel@tonic-gate 	    // Attempt to report error. Can't use Assert here because it
16550Sstevel@tonic-gate 	    //  calls back into SLPConfig.
16560Sstevel@tonic-gate 	    String msg = "Can''t find message ``{0}''''.";
16570Sstevel@tonic-gate 
16580Sstevel@tonic-gate 	    try {
16590Sstevel@tonic-gate 		pattern = bundle.getString("cant_find_resource");
16600Sstevel@tonic-gate 		msg = MessageFormat.format(pattern, new Object[] {msgTag});
16610Sstevel@tonic-gate 
16620Sstevel@tonic-gate 	    } catch (MissingResourceException exx) {
16630Sstevel@tonic-gate 
16640Sstevel@tonic-gate 	    }
16650Sstevel@tonic-gate 
16660Sstevel@tonic-gate 	    System.err.println(msg);
16670Sstevel@tonic-gate 	    System.exit(-1);
16680Sstevel@tonic-gate 	}
16690Sstevel@tonic-gate 
16700Sstevel@tonic-gate 	convertToString(params);
16710Sstevel@tonic-gate 
16720Sstevel@tonic-gate 	return MessageFormat.format(pattern, params);
16730Sstevel@tonic-gate     }
16740Sstevel@tonic-gate 
16750Sstevel@tonic-gate     // logging.
16760Sstevel@tonic-gate 
16770Sstevel@tonic-gate     // Protected so slpd can replace it.
16780Sstevel@tonic-gate 
16790Sstevel@tonic-gate     protected Writer log;
16800Sstevel@tonic-gate 
16810Sstevel@tonic-gate     // Synchronized so writes from multiple threads don't get interleaved.
16820Sstevel@tonic-gate 
writeLog(String msgTag, Object[] params)16830Sstevel@tonic-gate     void writeLog(String msgTag, Object[] params) {
16840Sstevel@tonic-gate 
16850Sstevel@tonic-gate 	// MessageFormat is picky about types. Convert the params into strings.
16860Sstevel@tonic-gate 
16870Sstevel@tonic-gate 	convertToString(params);
16880Sstevel@tonic-gate 
16890Sstevel@tonic-gate 	try {
16900Sstevel@tonic-gate 	    synchronized (log) {
16910Sstevel@tonic-gate 		log.write(formatMessage(msgTag, params));
16920Sstevel@tonic-gate 		log.flush();
16930Sstevel@tonic-gate 	    }
16940Sstevel@tonic-gate 	} catch (IOException ex) {}
16950Sstevel@tonic-gate     }
16960Sstevel@tonic-gate 
writeLogLine(String msgTag, Object[] params)16970Sstevel@tonic-gate     void writeLogLine(String msgTag, Object[] params) {
16980Sstevel@tonic-gate 
16990Sstevel@tonic-gate 	try {
17000Sstevel@tonic-gate 	    String pattern = getMessageBundle(getLocale()).getString(msgTag);
17010Sstevel@tonic-gate 
17020Sstevel@tonic-gate 	    synchronized (log) {
17030Sstevel@tonic-gate 		log.write(formatMessage(msgTag, params));
17040Sstevel@tonic-gate 		log.write("\n");
17050Sstevel@tonic-gate 		log.flush();
17060Sstevel@tonic-gate 	    }
17070Sstevel@tonic-gate 	} catch (IOException ex) {}
17080Sstevel@tonic-gate 
17090Sstevel@tonic-gate     }
17100Sstevel@tonic-gate 
getDateString()17110Sstevel@tonic-gate     static String getDateString() {
17120Sstevel@tonic-gate 
17130Sstevel@tonic-gate 	DateFormat df = DateFormat.getDateTimeInstance(DateFormat.DEFAULT,
17140Sstevel@tonic-gate 						       DateFormat.DEFAULT,
17150Sstevel@tonic-gate 						       getLocale());
17160Sstevel@tonic-gate 	Calendar calendar = Calendar.getInstance(getLocale());
17170Sstevel@tonic-gate 	return df.format(calendar.getTime());
17180Sstevel@tonic-gate 
17190Sstevel@tonic-gate     }
17200Sstevel@tonic-gate 
17210Sstevel@tonic-gate 
17220Sstevel@tonic-gate     // On load, check whether the signature class is available, and turn
17230Sstevel@tonic-gate     //  security off if not.
17240Sstevel@tonic-gate 
17250Sstevel@tonic-gate     static {
17260Sstevel@tonic-gate 
17270Sstevel@tonic-gate 	securityEnabled = true;
17280Sstevel@tonic-gate 	try {
17290Sstevel@tonic-gate 	    Class c = Class.forName("com.sun.slp.AuthBlock");
17300Sstevel@tonic-gate 
17310Sstevel@tonic-gate 	} catch (ClassNotFoundException e) {
17320Sstevel@tonic-gate 	    securityEnabled = false;
17330Sstevel@tonic-gate 	}
17340Sstevel@tonic-gate     }
17350Sstevel@tonic-gate 
17360Sstevel@tonic-gate }
1737